Skip to content

Commit e443372

Browse files
committed
net: initial proxy_protocol implementation
1 parent 2a1c511 commit e443372

15 files changed

Lines changed: 611 additions & 25 deletions

File tree

ip_addr.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include <arpa/inet.h>
4242
#include <netdb.h>
4343
#include "str.h"
44+
#include "net/proxy_protocol.h"
4445

4546

4647
#include "dprint.h"
@@ -86,6 +87,17 @@ union sockaddr_union{
8687
struct sockaddr_in6 sin6;
8788
};
8889

90+
enum proxy_protocol_flags {
91+
PP_INIT, PP_ERROR, PP_UNKNOWN, PP_OK
92+
};
93+
94+
struct proxy_protocol {
95+
enum proxy_protocol_flags flags;
96+
struct ip_addr src_ip;
97+
struct ip_addr dst_ip;
98+
unsigned short src_port; /*!< host byte order */
99+
unsigned short dst_port; /*!< host byte order */
100+
};
89101

90102

91103
enum si_flags { SI_NONE=0, SI_IS_IP=1, SI_IS_LO=2, SI_IS_MCAST=4,
@@ -101,9 +113,19 @@ struct receive_info {
101113
unsigned int proto_reserved2;
102114
union sockaddr_union src_su; /*!< useful for replies*/
103115
const struct socket_info* bind_address; /*!< sock_info structure on which the msg was received*/
116+
struct proxy_protocol real_ep; /*!< real endpoint of the mssage (behind a proxy protocol) */
104117
/* no need for dst_su yet */
105118
};
106119

120+
#define get_rcv_src_ip(_rcv) \
121+
(((_rcv)->real_ep.flags == PP_OK)?&(_rcv)->real_ep.src_ip:&(_rcv)->src_ip)
122+
#define get_rcv_src_port(_rcv) \
123+
(((_rcv)->real_ep.flags == PP_OK)?(_rcv)->real_ep.src_port:(_rcv)->src_port)
124+
#define get_rcv_dst_ip(_rcv) \
125+
(((_rcv)->real_ep.flags == PP_OK)?&(_rcv)->real_ep.dst_ip:&(_rcv)->dst_ip)
126+
#define get_rcv_dst_port(_rcv) \
127+
(((_rcv)->real_ep.flags == PP_OK)?(_rcv)->real_ep.dst_port:(_rcv)->dst_port)
128+
107129

108130
struct dest_info {
109131
int proto;

modules/pike/pike_funcs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ int pike_check_req(struct sip_msg *msg)
113113
if (ip==0)
114114
return -1;
115115
#else
116-
ip = &(msg->rcv.src_ip);
116+
ip = get_rcv_src_ip(&msg->rcv);
117117
#endif
118118

119119

modules/proto_tls/proto_tls.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,15 @@ static int tls_read_req(struct tcp_connection* con, int* bytes_read)
651651
req=&tls_current_req;
652652
}
653653

654+
switch (check_tcp_proxy_protocol(con)) {
655+
case 0:
656+
goto done;
657+
case -1:
658+
goto error;
659+
case 1:
660+
break;
661+
}
662+
654663
/* do this trick in order to trace whether if it's an error or not */
655664
ret=tls_mgm_api.tls_fix_read_conn(con, con->fd, tls_handshake_tout, t_dst, 1);
656665

modules/tracer/tracer.c

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2136,7 +2136,7 @@ static int sip_trace(struct sip_msg *msg, trace_info_p info, int leg_flag)
21362136
}
21372137

21382138
set_sock_columns( db_vals[4], db_vals[5], db_vals[6], fromip_buff,
2139-
&msg->rcv.src_ip, msg->rcv.src_port, msg->rcv.proto);
2139+
get_rcv_src_ip(&msg->rcv), get_rcv_src_port(&msg->rcv), msg->rcv.proto);
21402140

21412141
set_sock_columns( db_vals[7], db_vals[8], db_vals[9], toip_buff,
21422142
TRACE_GET_DST_IP(msg), TRACE_GET_DST_PORT(msg), msg->rcv.proto);
@@ -2223,7 +2223,7 @@ static int sip_trace_instance(struct sip_msg* msg,
22232223
}
22242224

22252225
set_sock_columns( db_vals[4], db_vals[5], db_vals[6], fromip_buff,
2226-
&msg->rcv.src_ip, msg->rcv.src_port, msg->rcv.proto);
2226+
get_rcv_src_ip(&msg->rcv), get_rcv_src_port(&msg->rcv), msg->rcv.proto);
22272227

22282228
set_sock_columns( db_vals[7], db_vals[8], db_vals[9], toip_buff,
22292229
TRACE_GET_DST_IP(msg), TRACE_GET_DST_PORT(msg), msg->rcv.proto);
@@ -2449,9 +2449,11 @@ static void trace_msg_out(struct sip_msg* msg, str *sbuf,
24492449
{
24502450
static char fromip_buff[IP_ADDR_MAX_STR_SIZE+12];
24512451
static char toip_buff[IP_ADDR_MAX_STR_SIZE+12];
2452-
struct ip_addr to_ip;
2452+
struct ip_addr to_ip, *ip;
2453+
struct receive_info ri;
24532454
trace_instance_p instance;
24542455
str from_tag;
2456+
unsigned int port;
24552457

24562458
if(parse_from_and_callid(msg, &from_tag) != 0)
24572459
{
@@ -2513,12 +2515,18 @@ static void trace_msg_out(struct sip_msg* msg, str *sbuf,
25132515
{
25142516
set_columns_to_any(db_vals[7], db_vals[8], db_vals[9]);
25152517
} else {
2518+
if (proto != PROTO_UDP && info->conn_id &&
2519+
tcp_get_rcv(info->conn_id, &ri) == 0) {
2520+
ip = get_rcv_src_ip(&ri);
2521+
port = get_rcv_src_port(&ri);
2522+
} else {
2523+
ip = &to_ip;
2524+
port = (unsigned int)(send_sock && send_sock->last_real_ports->remote?
2525+
send_sock->last_real_ports->remote:su_getport(to));
2526+
}
25162527
su2ip_addr(&to_ip, to);
25172528
set_sock_columns( db_vals[7], db_vals[8], db_vals[9], toip_buff,
2518-
&to_ip,
2519-
(unsigned long)(send_sock && send_sock->last_real_ports->remote?
2520-
send_sock->last_real_ports->remote:su_getport(to)),
2521-
proto);
2529+
ip, port, proto);
25222530
}
25232531

25242532
db_vals[10].val.time_val = time(NULL);
@@ -2621,7 +2629,7 @@ static void trace_onreply_in(struct cell* t, int type, struct tmcb_params *ps,
26212629
db_vals[3].val.str_val.len = len;
26222630

26232631
set_sock_columns( db_vals[4], db_vals[5], db_vals[6], fromip_buff,
2624-
&msg->rcv.src_ip, msg->rcv.src_port, msg->rcv.proto);
2632+
get_rcv_src_ip(&msg->rcv), get_rcv_src_port(&msg->rcv), msg->rcv.proto);
26252633

26262634
if(trace_local_ip.s && trace_local_ip.len > 0){
26272635
set_columns_to_trace_local_ip(db_vals[7], db_vals[8], db_vals[9]);
@@ -2690,12 +2698,14 @@ static void trace_onreply_out(struct cell* t, int type, struct tmcb_params *ps,
26902698
static char toip_buff[IP_ADDR_MAX_STR_SIZE+12];
26912699
trace_instance_p instance;
26922700
struct sip_msg* msg;
2693-
struct ip_addr to_ip;
2701+
struct ip_addr to_ip, *ip;
2702+
struct receive_info ri;
26942703
int len;
26952704
char statusbuf[8];
26962705
str *sbuf;
26972706
struct dest_info *dst;
26982707
str from_tag;
2708+
unsigned int port;
26992709

27002710
trace_info_t info;
27012711

@@ -2797,13 +2807,19 @@ static void trace_onreply_out(struct cell* t, int type, struct tmcb_params *ps,
27972807
{
27982808
set_columns_to_any( db_vals[7], db_vals[8], db_vals[9]);
27992809
} else {
2810+
if (dst->proto != PROTO_UDP && info.conn_id &&
2811+
tcp_get_rcv(info.conn_id, &ri) == 0) {
2812+
ip = get_rcv_src_ip(&ri);
2813+
port = get_rcv_src_port(&ri);
2814+
} else {
2815+
ip = &to_ip;
2816+
port = (unsigned int)(dst->send_sock && dst->send_sock->last_real_ports->remote?
2817+
dst->send_sock->last_real_ports->remote:su_getport(&dst->to));
2818+
}
28002819
memset(&to_ip, 0, sizeof(struct ip_addr));
28012820
su2ip_addr(&to_ip, &dst->to);
28022821
set_sock_columns( db_vals[7], db_vals[8], db_vals[9], toip_buff,
2803-
&to_ip,
2804-
(unsigned long)(dst->send_sock && dst->send_sock->last_real_ports->remote?
2805-
dst->send_sock->last_real_ports->remote:su_getport(&dst->to)),
2806-
dst->proto);
2822+
ip, port, dst->proto);
28072823
}
28082824

28092825
db_vals[10].val.time_val = time(NULL);

net/net_tcp.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,21 @@ int tcp_get_correlation_id( unsigned int id, unsigned long long *cid)
468468
return -1;
469469
}
470470

471+
/* returns the correlation ID of a TCP connection */
472+
int tcp_get_rcv( unsigned int id, struct receive_info *ri)
473+
{
474+
struct tcp_connection* c;
475+
476+
TCPCONN_LOCK(id);
477+
if ( (c=_tcpconn_find(id))!=NULL ) {
478+
memcpy(ri, &c->rcv, sizeof *ri);
479+
TCPCONN_UNLOCK(id);
480+
return 0;
481+
}
482+
TCPCONN_UNLOCK(id);
483+
return -1;
484+
}
485+
471486

472487
/*! \brief _tcpconn_find with locks and acquire fd */
473488
int tcp_conn_get(unsigned int id, struct ip_addr* ip, int port,

net/net_tcp.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ int tcp_conn_fcntl(struct receive_info *rcv, int attr, void *value);
110110
/* returns the correlation ID of a TCP connection */
111111
int tcp_get_correlation_id( unsigned int id, unsigned long long *cid);
112112

113+
/* returns the receive_info of a TCP connection */
114+
int tcp_get_rcv(unsigned int id, struct receive_info *ri);
115+
113116
int tcp_done_reading(struct tcp_connection* c);
114117

115118
extern unsigned int last_outgoing_tcp_id;

net/proto_tcp/proto_tcp.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -651,7 +651,7 @@ int tcp_read(struct tcp_connection *c,struct tcp_req *r)
651651
*/
652652
static int tcp_read_req(struct tcp_connection* con, int* bytes_read)
653653
{
654-
int bytes, rc;
654+
int bytes, rc = 0;
655655
int total_bytes;
656656
struct tcp_req* req;
657657

@@ -688,6 +688,15 @@ static int tcp_read_req(struct tcp_connection* con, int* bytes_read)
688688
req=&tcp_current_req;
689689
}
690690

691+
switch (check_tcp_proxy_protocol(con)) {
692+
case 0:
693+
goto done;
694+
case -1:
695+
goto error;
696+
case 1:
697+
break;
698+
}
699+
691700
again:
692701
if(req->error==TCP_REQ_OK){
693702
/* if we still have some unparsed part, parse it first,

net/proto_udp/proto_udp.c

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "../api_proto.h"
3838
#include "../api_proto_net.h"
3939
#include "../net_udp.h"
40+
#include "../proxy_protocol.h"
4041
#include "proto_udp.h"
4142

4243

@@ -149,14 +150,6 @@ static int udp_read_req(const struct socket_info *si, int* bytes_read)
149150
return -2;
150151
}
151152

152-
if (len<MIN_UDP_PACKET) {
153-
LM_DBG("probing packet received len = %d\n", len);
154-
return 0;
155-
}
156-
157-
/* we must 0-term the messages, receive_msg expects it */
158-
buf[len]=0; /* no need to save the previous char */
159-
160153
ri.bind_address = si;
161154
ri.dst_port = si->port_no;
162155
ri.dst_ip = si->address;
@@ -169,6 +162,17 @@ static int udp_read_req(const struct socket_info *si, int* bytes_read)
169162
msg.s = buf;
170163
msg.len = len;
171164

165+
if (check_udp_proxy_protocol(&msg.s, &msg.len, &ri) < 0)
166+
return 0;
167+
168+
if (msg.len<MIN_UDP_PACKET) {
169+
LM_DBG("probing packet received len = %d\n", msg.len);
170+
return 0;
171+
}
172+
173+
/* we must 0-term the messages, receive_msg expects it */
174+
msg.s[msg.len]=0; /* no need to save the previous char */
175+
172176
/* run callbacks if looks like non-SIP message*/
173177
if( !isalpha(msg.s[0]) ){ /* not-SIP related */
174178
for(p = cb_list; p; p = p->next){
@@ -257,4 +261,3 @@ int register_udprecv_cb(udp_rcv_cb_f* func, void* param, char a, char b)
257261

258262

259263

260-

0 commit comments

Comments
 (0)