Browse code

core: Fixes for WSS (secure WebSocket) transport and Via:s

Peter Dunkley authored on 04/07/2012 15:12:53
Showing 4 changed files
... ...
@@ -253,8 +253,10 @@ struct socket_info* get_send_socket2(struct socket_info* force_send_socket,
253 253
 	if (likely(mismatch)) *mismatch=0;
254 254
 	/* check if send interface is not forced */
255 255
 	if (unlikely(force_send_socket)){
256
-		if (unlikely(force_send_socket->proto!=proto)){
257
-			orig=force_send_socket;
256
+		orig=force_send_socket;
257
+		/* Special case here as there is no ;transport=wss - so wss connections will
258
+		   appear as ws ones and be sorted out in the WebSocket module */
259
+		if (unlikely(orig->proto!=proto && !(orig->proto==PROTO_TLS && proto==PROTO_WS))){
258 260
 			force_send_socket=find_si(&(force_send_socket->address),
259 261
 											force_send_socket->port_no,
260 262
 											proto);
... ...
@@ -648,19 +648,25 @@ static inline int lumps_len(struct sip_msg* msg, struct lump* lumps,
648 648
 				break; \
649 649
 			case SUBST_RCV_PROTO: \
650 650
 				if (msg->rcv.bind_address){ \
651
-					switch(msg->rcv.proto){ \
651
+					switch(msg->rcv.bind_address->proto){ \
652 652
 						case PROTO_NONE: \
653 653
 						case PROTO_UDP: \
654
+							new_len+=3; \
655
+							break; \
654 656
 						case PROTO_TCP: \
655 657
 						case PROTO_TLS: \
656
-								new_len+=3; \
657
-								break; \
658
-						case PROTO_SCTP: \
659
-								new_len+=4; \
658
+							switch(msg->rcv.proto){ \
659
+								case PROTO_WS: \
660
+								case PROTO_WSS: \
661
+									new_len+=2; \
662
+									break; \
663
+								default: \
664
+									new_len+=3; \
665
+									break; \
666
+							} \
660 667
 							break; \
661
-						case PROTO_WS: \
662
-						case PROTO_WSS: \
663
-							new_len+=2; \
668
+						case PROTO_SCTP: \
669
+							new_len+=4; \
664 670
 							break; \
665 671
 						default: \
666 672
 						LOG(L_CRIT, "BUG: lumps_len: unknown proto %d\n", \
... ...
@@ -681,21 +687,25 @@ static inline int lumps_len(struct sip_msg* msg, struct lump* lumps,
681 681
 						new_len+=1+recv_port_str->len; \
682 682
 					}\
683 683
 						/*add;transport=xxx*/ \
684
-					switch(msg->rcv.proto){ \
684
+					switch(msg->rcv.bind_address->proto){ \
685 685
 						case PROTO_NONE: \
686 686
 						case PROTO_UDP: \
687
-								break; /* udp is the default */ \
687
+							break; /* udp is the default */ \
688 688
 						case PROTO_TCP: \
689 689
 						case PROTO_TLS: \
690
-								new_len+=TRANSPORT_PARAM_LEN+3; \
691
-								break; \
690
+							switch(msg->rcv.proto){ \
691
+								case PROTO_WS: \
692
+								case PROTO_WSS: \
693
+									new_len+=TRANSPORT_PARAM_LEN+2; \
694
+									break; \
695
+								default: \
696
+									new_len+=TRANSPORT_PARAM_LEN+3; \
697
+									break; \
698
+							} \
699
+							break; \
692 700
 						case PROTO_SCTP: \
693
-								new_len+=TRANSPORT_PARAM_LEN+4; \
694
-								break; \
695
-						case PROTO_WS: \
696
-						case PROTO_WSS: \
697
-								new_len+=TRANSPORT_PARAM_LEN+2; \
698
-								break; \
701
+							new_len+=TRANSPORT_PARAM_LEN+4; \
702
+							break; \
699 703
 						default: \
700 704
 						LOG(L_CRIT, "BUG: lumps_len: unknown proto %d\n", \
701 705
 								msg->rcv.bind_address->proto); \
... ...
@@ -727,20 +737,26 @@ static inline int lumps_len(struct sip_msg* msg, struct lump* lumps,
727 727
 				break; \
728 728
 			case SUBST_SND_PROTO: \
729 729
 				if (send_sock){ \
730
-					switch(send_info->proto){ \
730
+					switch(send_sock->proto){ \
731 731
 						case PROTO_NONE: \
732 732
 						case PROTO_UDP: \
733
+							new_len+=3; \
734
+							break; \
733 735
 						case PROTO_TCP: \
734 736
 						case PROTO_TLS: \
735
-								new_len+=3; \
736
-								break; \
737
+							switch(send_info->proto){ \
738
+								case PROTO_WS: \
739
+								case PROTO_WSS: \
740
+									new_len+=2; \
741
+									break; \
742
+								default: \
743
+									new_len+=3; \
744
+									break; \
745
+							} \
746
+							break; \
737 747
 						case PROTO_SCTP: \
738
-								new_len+=4; \
739
-								break; \
740
-						case PROTO_WS: \
741
-						case PROTO_WSS: \
742
-								new_len+=2; \
743
-								break; \
748
+							new_len+=4; \
749
+							break; \
744 750
 						default: \
745 751
 						LOG(L_CRIT, "BUG: lumps_len: unknown proto %d\n", \
746 752
 								send_sock->proto); \
... ...
@@ -762,21 +778,25 @@ static inline int lumps_len(struct sip_msg* msg, struct lump* lumps,
762 762
 						new_len+=1+send_port_str->len; \
763 763
 					}\
764 764
 					/*add;transport=xxx*/ \
765
-					switch(send_info->proto){ \
765
+					switch(send_sock->proto){ \
766 766
 						case PROTO_NONE: \
767 767
 						case PROTO_UDP: \
768
-								break; /* udp is the default */ \
768
+							break; /* udp is the default */ \
769 769
 						case PROTO_TCP: \
770 770
 						case PROTO_TLS: \
771
-								new_len+=TRANSPORT_PARAM_LEN+3; \
772
-								break; \
771
+							switch(send_info->proto){ \
772
+								case PROTO_WS: \
773
+								case PROTO_WSS: \
774
+									new_len+=TRANSPORT_PARAM_LEN+2; \
775
+									break; \
776
+								default: \
777
+									new_len+=TRANSPORT_PARAM_LEN+3; \
778
+									break; \
779
+							} \
780
+							break; \
773 781
 						case PROTO_SCTP: \
774
-								new_len+=TRANSPORT_PARAM_LEN+4; \
775
-								break; \
776
-						case PROTO_WS: \
777
-						case PROTO_WSS: \
778
-								new_len+=TRANSPORT_PARAM_LEN+2; \
779
-								break; \
782
+							new_len+=TRANSPORT_PARAM_LEN+4; \
783
+							break; \
780 784
 						default: \
781 785
 						LOG(L_CRIT, "BUG: lumps_len: unknown proto %d\n", \
782 786
 								send_sock->proto); \
... ...
@@ -1042,7 +1062,7 @@ static inline void process_lumps(	struct sip_msg* msg,
1042 1042
 							recv_port_str->len); \
1043 1043
 					offset+=recv_port_str->len; \
1044 1044
 				}\
1045
-				switch(msg->rcv.proto){ \
1045
+				switch(msg->rcv.bind_address->proto){ \
1046 1046
 					case PROTO_NONE: \
1047 1047
 					case PROTO_UDP: \
1048 1048
 						break; /* nothing to do, udp is default*/ \
... ...
@@ -1050,15 +1070,25 @@ static inline void process_lumps(	struct sip_msg* msg,
1050 1050
 						memcpy(new_buf+offset, TRANSPORT_PARAM, \
1051 1051
 								TRANSPORT_PARAM_LEN); \
1052 1052
 						offset+=TRANSPORT_PARAM_LEN; \
1053
-						memcpy(new_buf+offset, "tcp", 3); \
1054
-						offset+=3; \
1053
+						if (msg->rcv.proto == PROTO_WS) { \
1054
+							memcpy(new_buf+offset, "ws", 2); \
1055
+							offset+=2; \
1056
+						} else { \
1057
+							memcpy(new_buf+offset, "tcp", 3); \
1058
+							offset+=3; \
1059
+						} \
1055 1060
 						break; \
1056 1061
 					case PROTO_TLS: \
1057 1062
 						memcpy(new_buf+offset, TRANSPORT_PARAM, \
1058 1063
 								TRANSPORT_PARAM_LEN); \
1059 1064
 						offset+=TRANSPORT_PARAM_LEN; \
1060
-						memcpy(new_buf+offset, "tls", 3); \
1061
-						offset+=3; \
1065
+						if (msg->rcv.proto == PROTO_WS || msg->rcv.proto == PROTO_WSS) { \
1066
+							memcpy(new_buf+offset, "ws", 2); \
1067
+							offset+=2; \
1068
+						} else { \
1069
+							memcpy(new_buf+offset, "tls", 3); \
1070
+							offset+=3; \
1071
+						} \
1062 1072
 						break; \
1063 1073
 					case PROTO_SCTP: \
1064 1074
 						memcpy(new_buf+offset, TRANSPORT_PARAM, \
... ...
@@ -1067,14 +1097,6 @@ static inline void process_lumps(	struct sip_msg* msg,
1067 1067
 						memcpy(new_buf+offset, "sctp", 4); \
1068 1068
 						offset+=4; \
1069 1069
 						break; \
1070
-					case PROTO_WS: \
1071
-					case PROTO_WSS: \
1072
-						memcpy(new_buf+offset, TRANSPORT_PARAM, \
1073
-								TRANSPORT_PARAM_LEN); \
1074
-						offset+=TRANSPORT_PARAM_LEN; \
1075
-						memcpy(new_buf+offset, "ws", 2); \
1076
-						offset+=2; \
1077
-						break; \
1078 1070
 					default: \
1079 1071
 						LOG(L_CRIT, "BUG: process_lumps: unknown proto %d\n", \
1080 1072
 								msg->rcv.bind_address->proto); \
... ...
@@ -1137,7 +1159,7 @@ static inline void process_lumps(	struct sip_msg* msg,
1137 1137
 							send_port_str->len); \
1138 1138
 					offset+=send_port_str->len; \
1139 1139
 				}\
1140
-				switch(send_info->proto){ \
1140
+				switch(send_sock->proto){ \
1141 1141
 					case PROTO_NONE: \
1142 1142
 					case PROTO_UDP: \
1143 1143
 						break; /* nothing to do, udp is default*/ \
... ...
@@ -1145,15 +1167,25 @@ static inline void process_lumps(	struct sip_msg* msg,
1145 1145
 						memcpy(new_buf+offset, TRANSPORT_PARAM, \
1146 1146
 								TRANSPORT_PARAM_LEN); \
1147 1147
 						offset+=TRANSPORT_PARAM_LEN; \
1148
-						memcpy(new_buf+offset, "tcp", 3); \
1149
-						offset+=3; \
1148
+						if (send_info->proto == PROTO_WS) { \
1149
+							memcpy(new_buf+offset, "ws", 2); \
1150
+							offset+=2; \
1151
+						} else { \
1152
+							memcpy(new_buf+offset, "tcp", 3); \
1153
+							offset+=3; \
1154
+						} \
1150 1155
 						break; \
1151 1156
 					case PROTO_TLS: \
1152 1157
 						memcpy(new_buf+offset, TRANSPORT_PARAM, \
1153 1158
 								TRANSPORT_PARAM_LEN); \
1154 1159
 						offset+=TRANSPORT_PARAM_LEN; \
1155
-						memcpy(new_buf+offset, "tls", 3); \
1156
-						offset+=3; \
1160
+						if (send_info->proto == PROTO_WS || send_info->proto == PROTO_WSS) { \
1161
+							memcpy(new_buf+offset, "ws", 2); \
1162
+							offset+=2; \
1163
+						} else { \
1164
+							memcpy(new_buf+offset, "tls", 3); \
1165
+							offset+=3; \
1166
+						} \
1157 1167
 						break; \
1158 1168
 					case PROTO_SCTP: \
1159 1169
 						memcpy(new_buf+offset, TRANSPORT_PARAM, \
... ...
@@ -1162,14 +1194,6 @@ static inline void process_lumps(	struct sip_msg* msg,
1162 1162
 						memcpy(new_buf+offset, "sctp", 4); \
1163 1163
 						offset+=4; \
1164 1164
 						break; \
1165
-					case PROTO_WS: \
1166
-					case PROTO_WSS: \
1167
-						memcpy(new_buf+offset, TRANSPORT_PARAM, \
1168
-								TRANSPORT_PARAM_LEN); \
1169
-						offset+=TRANSPORT_PARAM_LEN; \
1170
-						memcpy(new_buf+offset, "ws", 2); \
1171
-						offset+=2; \
1172
-						break; \
1173 1165
 					default: \
1174 1166
 						LOG(L_CRIT, "BUG: process_lumps: unknown proto %d\n", \
1175 1167
 								send_sock->proto); \
... ...
@@ -1182,29 +1206,34 @@ static inline void process_lumps(	struct sip_msg* msg,
1182 1182
 			break; \
1183 1183
 		case SUBST_RCV_PROTO: \
1184 1184
 			if (msg->rcv.bind_address){ \
1185
-				switch(msg->rcv.proto){ \
1185
+				switch(msg->rcv.bind_address->proto){ \
1186 1186
 					case PROTO_NONE: \
1187 1187
 					case PROTO_UDP: \
1188 1188
 						memcpy(new_buf+offset, "udp", 3); \
1189 1189
 						offset+=3; \
1190 1190
 						break; \
1191 1191
 					case PROTO_TCP: \
1192
-						memcpy(new_buf+offset, "tcp", 3); \
1193
-						offset+=3; \
1192
+						if (msg->rcv.proto == PROTO_WS) { \
1193
+							memcpy(new_buf+offset, "ws", 2); \
1194
+							offset+=2; \
1195
+						} else { \
1196
+							memcpy(new_buf+offset, "tcp", 3); \
1197
+							offset+=3; \
1198
+						} \
1194 1199
 						break; \
1195 1200
 					case PROTO_TLS: \
1196
-						memcpy(new_buf+offset, "tls", 3); \
1197
-						offset+=3; \
1201
+						if (msg->rcv.proto == PROTO_WS || msg->rcv.proto == PROTO_WSS) { \
1202
+							memcpy(new_buf+offset, "ws", 2); \
1203
+							offset+=2; \
1204
+						} else { \
1205
+							memcpy(new_buf+offset, "tls", 3); \
1206
+							offset+=3; \
1207
+						} \
1198 1208
 						break; \
1199 1209
 					case PROTO_SCTP: \
1200 1210
 						memcpy(new_buf+offset, "sctp", 4); \
1201 1211
 						offset+=4; \
1202 1212
 						break; \
1203
-					case PROTO_WS: \
1204
-					case PROTO_WSS: \
1205
-						memcpy(new_buf+offset, "ws", 2); \
1206
-						offset+=2; \
1207
-						break; \
1208 1213
 					default: \
1209 1214
 						LOG(L_CRIT, "BUG: process_lumps: unknown proto %d\n", \
1210 1215
 								msg->rcv.bind_address->proto); \
... ...
@@ -1217,29 +1246,34 @@ static inline void process_lumps(	struct sip_msg* msg,
1217 1217
 			break; \
1218 1218
 		case  SUBST_SND_PROTO: \
1219 1219
 			if (send_sock){ \
1220
-				switch(send_info->proto){ \
1220
+				switch(send_sock->proto){ \
1221 1221
 					case PROTO_NONE: \
1222 1222
 					case PROTO_UDP: \
1223 1223
 						memcpy(new_buf+offset, "udp", 3); \
1224 1224
 						offset+=3; \
1225 1225
 						break; \
1226 1226
 					case PROTO_TCP: \
1227
-						memcpy(new_buf+offset, "tcp", 3); \
1228
-						offset+=3; \
1227
+						if (send_info->proto == PROTO_WS) { \
1228
+							memcpy(new_buf+offset, "ws", 2); \
1229
+							offset+=2; \
1230
+						} else { \
1231
+							memcpy(new_buf+offset, "tcp", 3); \
1232
+							offset+=3; \
1233
+						} \
1229 1234
 						break; \
1230 1235
 					case PROTO_TLS: \
1231
-						memcpy(new_buf+offset, "tls", 3); \
1232
-						offset+=3; \
1236
+						if (send_info->proto == PROTO_WS || send_info->proto == PROTO_WSS) { \
1237
+							memcpy(new_buf+offset, "ws", 2); \
1238
+							offset+=2; \
1239
+						} else { \
1240
+							memcpy(new_buf+offset, "tls", 3); \
1241
+							offset+=3; \
1242
+						} \
1233 1243
 						break; \
1234 1244
 					case PROTO_SCTP: \
1235 1245
 						memcpy(new_buf+offset, "sctp", 4); \
1236 1246
 						offset+=4; \
1237 1247
 						break; \
1238
-					case PROTO_WS: \
1239
-					case PROTO_WSS: \
1240
-						memcpy(new_buf+offset, "ws", 2); \
1241
-						offset+=4; \
1242
-						break; \
1243 1248
 					default: \
1244 1249
 						LOG(L_CRIT, "BUG: process_lumps: unknown proto %d\n", \
1245 1250
 								send_sock->proto); \
... ...
@@ -2369,6 +2403,11 @@ char* via_builder( unsigned int *len,
2369 2369
 #ifdef USE_COMP
2370 2370
 	char* comp_name;
2371 2371
 #endif /* USE_COMP */
2372
+	int port;
2373
+	struct ip_addr ip;
2374
+	union sockaddr_union *from = NULL;
2375
+	union sockaddr_union local_addr;
2376
+	struct tcp_connection *con = NULL;
2372 2377
 
2373 2378
 	send_sock=send_info->send_sock;
2374 2379
 	/* use pre-set address in via, the outbound socket alias or address one */
... ...
@@ -2437,7 +2476,38 @@ char* via_builder( unsigned int *len,
2437 2437
 	}else if (send_info->proto==PROTO_SCTP){
2438 2438
 		memcpy(line_buf+MY_VIA_LEN-4, "SCTP ", 5);
2439 2439
 	}else if (send_info->proto==PROTO_WS){
2440
-		memcpy(line_buf+MY_VIA_LEN-4, "WS ", 3);
2440
+                if (unlikely(send_info->send_flags.f & SND_F_FORCE_SOCKET
2441
+                                && send_info->send_sock)) {
2442
+                        local_addr = send_info->send_sock->su;
2443
+                        su_setport(&local_addr, 0); /* any local port will do */
2444
+                        from = &local_addr;
2445
+                }
2446
+
2447
+                port = su_getport(&send_info->to);
2448
+                if (likely(port)) {
2449
+                        su2ip_addr(&ip, &send_info->to);
2450
+                        con = tcpconn_get(send_info->id, &ip, port, from, 0);
2451
+                }
2452
+                else if (likely(send_info->id))
2453
+                        con = tcpconn_get(send_info->id, 0, 0, 0, 0);
2454
+                else {
2455
+                        LM_CRIT("BUG: via_builder called with null_id & to\n");
2456
+                        return 0;
2457
+                }
2458
+
2459
+                if (con == NULL) {
2460
+                        LM_WARN("TCP/TLS connection for WebSocket could not be found\n");
2461
+                        return 0;
2462
+                }
2463
+
2464
+		if (con->rcv.proto==PROTO_WS) {
2465
+			memcpy(line_buf+MY_VIA_LEN-4, "WS ", 3);
2466
+		} else if (con->rcv.proto==PROTO_WSS) {
2467
+			memcpy(line_buf+MY_VIA_LEN-4, "WSS ", 4);
2468
+		} else {
2469
+			LOG(L_CRIT, "BUG: via_builder: unknown proto %d\n", con->rcv.proto);
2470
+			return 0;
2471
+		}
2441 2472
 	}else if (send_info->proto==PROTO_WSS){
2442 2473
 		memcpy(line_buf+MY_VIA_LEN-4, "WSS ", 4);
2443 2474
 	}else{
... ...
@@ -1427,6 +1427,7 @@ inline void proto_type_to_str(unsigned short type, str *s) {
1427 1427
 		*s = s_sctp;
1428 1428
 		break;
1429 1429
 	case PROTO_WS:
1430
+	case PROTO_WSS:
1430 1431
 		*s = s_ws;
1431 1432
 		break;
1432 1433
 	default:
... ...
@@ -570,7 +570,9 @@ struct socket_info* grep_sock_info(str* host, unsigned short port,
570 570
 		hname.len-=2;
571 571
 	}
572 572
 #endif
573
+
573 574
 	c_proto=(proto!=PROTO_NONE)?proto:PROTO_UDP;
575
+retry:
574 576
 	do{
575 577
 		/* get the proper sock_list */
576 578
 		list=get_sock_info_list(c_proto);
... ...
@@ -616,7 +618,15 @@ struct socket_info* grep_sock_info(str* host, unsigned short port,
616 616
 									&ai->address, ai->flags)==0)
617 617
 					goto found;
618 618
 		}
619
+
619 620
 	}while( (proto==0) && (c_proto=next_proto(c_proto)) );
621
+
622
+#ifdef USE_TLS
623
+	if (unlikely(c_proto == PROTO_WS)) {
624
+		c_proto = PROTO_WSS;
625
+		goto retry;
626
+	}
627
+#endif
620 628
 /* not_found: */
621 629
 	return 0;
622 630
 found: