Skip to content

Commit

Permalink
Re-work hostname validation support to not require every
Browse files Browse the repository at this point in the history
user of sockaddr_union to store a copy of the hostname.

Do this by creating a new "struct sockaddr_hu" struct,
which includes sockaddr_union as well as an optional
hostname. Extend various relevant APIs to use this
structure instead.

Push down that structure all the way to the
tls_mgm_api.tls_conn_init().

Untested.
  • Loading branch information
sobomax committed Nov 30, 2023
1 parent 5ea4ec8 commit cf2dad2
Show file tree
Hide file tree
Showing 67 changed files with 331 additions and 260 deletions.
8 changes: 4 additions & 4 deletions core_cmds.c
Original file line number Diff line number Diff line change
Expand Up @@ -745,13 +745,13 @@ static int w_forward(struct sip_msg *msg, struct proxy_l *dest)
static int w_send(struct sip_msg *msg, struct proxy_l *dest, str *headers)
{
int ret;
union sockaddr_union* to;
struct sockaddr_hu* to;
struct proxy_l* p;
int len;
char* tmp;

to=(union sockaddr_union*)
pkg_malloc(sizeof(union sockaddr_union));
to=(struct sockaddr_hu*)
pkg_malloc(sizeof(*to));
if (to==0){
LM_ERR("memory allocation failure\n");
return E_OUT_OF_MEM;
Expand All @@ -760,7 +760,7 @@ static int w_send(struct sip_msg *msg, struct proxy_l *dest, str *headers)
LM_ERR("failed to clone proxy, dropping packet\n");
return E_OUT_OF_MEM;
}
ret=hostent2su(to, &p->host, p->addr_idx,
ret=hostent2hu(to, &p->host, p->addr_idx,
(p->port)?p->port:SIP_PORT );
if (ret==0){
if (headers) {
Expand Down
26 changes: 13 additions & 13 deletions forward.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@
* be very likely noticeably slower, but it can deal better with
* multihomed hosts
*/
struct socket_info* get_out_socket(union sockaddr_union* to, int proto)
struct socket_info* get_out_socket(const union sockaddr_union* to, int proto)
{
int temp_sock;
socklen_t len;
Expand Down Expand Up @@ -143,7 +143,7 @@ struct socket_info* get_out_socket(union sockaddr_union* to, int proto)
* \note if msg!=null and msg->force_send_socket, the force_send_socket will be used
*/
struct socket_info* get_send_socket(struct sip_msg *msg,
union sockaddr_union* to, int proto)
const union sockaddr_union* to, int proto)
{
struct socket_info* send_sock;

Expand Down Expand Up @@ -306,7 +306,7 @@ static inline int set_sl_branch(struct sip_msg* msg)

int forward_request( struct sip_msg* msg, struct proxy_l * p)
{
union sockaddr_union to;
struct sockaddr_hu to;
str buf;
struct socket_info* send_sock;
struct socket_info* last_sock;
Expand All @@ -327,17 +327,17 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p)

msg_callback_process(msg, REQ_PRE_FORWARD, (void *)p);

hostent2su( &to, &p->host, p->addr_idx, (p->port)?p->port:SIP_PORT);
hostent2hu( &to, &p->host, p->addr_idx, (p->port)?p->port:SIP_PORT);
last_sock = 0;

if (getb0flags(msg) & tcp_no_new_conn_bflag)
tcp_no_new_conn = 1;

do {
send_sock=get_send_socket( msg, &to, p->proto);
send_sock=get_send_socket( msg, &to.su, p->proto);
if (send_sock==0){
LM_ERR("cannot forward to af %d, proto %d no corresponding"
"listening socket\n", to.s.sa_family, p->proto);
"listening socket\n", to.su.s.sa_family, p->proto);
ser_error=E_NO_SOCKET;
continue;
}
Expand All @@ -358,7 +358,7 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p)
last_sock = send_sock;
}

if (check_blacklists( p->proto, &to, buf.s, buf.len)) {
if (check_blacklists( p->proto, &to.su, buf.s, buf.len)) {
LM_DBG("blocked by blacklists\n");
ser_error=E_IP_BLOCKED;
continue;
Expand All @@ -379,7 +379,7 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p)
ser_error = 0;
break;

}while( get_next_su( p, &to, (ser_error==E_IP_BLOCKED)?0:1)==0 );
}while( get_next_hu( p, &to, (ser_error==E_IP_BLOCKED)?0:1)==0 );

tcp_no_new_conn = 0;

Expand All @@ -402,7 +402,7 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p)



int update_sock_struct_from_via( union sockaddr_union* to,
int update_sock_struct_from_via( struct sockaddr_hu* to,
struct sip_msg* msg,
struct via_body* via )
{
Expand Down Expand Up @@ -458,7 +458,7 @@ int update_sock_struct_from_via( union sockaddr_union* to,
return -1;
}

hostent2su( to, he, 0, port);
hostent2hu( to, he, 0, port);
return 1;
}

Expand All @@ -468,7 +468,7 @@ int update_sock_struct_from_via( union sockaddr_union* to,
int forward_reply(struct sip_msg* msg)
{
char* new_buf;
union sockaddr_union* to;
struct sockaddr_hu *to;
unsigned int new_len;
struct sr_module *mod;
int proto;
Expand Down Expand Up @@ -517,7 +517,7 @@ int forward_reply(struct sip_msg* msg)
goto error;
}

to=(union sockaddr_union*)pkg_malloc(sizeof(union sockaddr_union));
to=(struct sockaddr_hu *)pkg_malloc(sizeof(*to));
if (to==0){
LM_ERR("out of pkg memory\n");
goto error;
Expand All @@ -536,7 +536,7 @@ int forward_reply(struct sip_msg* msg)
}
}

send_sock = get_send_socket(msg, to, proto);
send_sock = get_send_socket(msg, &to->su, proto);

new_buf = build_res_buf_from_sip_res( msg, &new_len, send_sock,0);
if (!new_buf){
Expand Down
14 changes: 8 additions & 6 deletions forward.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,18 @@
#include "socket_info.h"

struct socket_info* get_send_socket(struct sip_msg* msg,
union sockaddr_union* su, int proto);
struct socket_info* get_out_socket(union sockaddr_union* to, int proto);
const union sockaddr_union* su, int proto);
struct socket_info* get_out_socket(const union sockaddr_union* to, int proto);
int check_self(str* host, unsigned short port, unsigned short proto);
int forward_request( struct sip_msg* msg, struct proxy_l* p);
int update_sock_struct_from_via( union sockaddr_union* to,
int update_sock_struct_from_via( struct sockaddr_hu* to,
struct sip_msg* msg,
struct via_body* via );

/*! \brief use src_ip, port=src_port if rport, via port if via port, 5060 otherwise */
#define update_sock_struct_from_ip( to, msg ) \
init_su((to), &(msg)->rcv.src_ip, \
*(to) = (struct sockaddr_hu){0}; \
init_su(&((to)->su), &(msg)->rcv.src_ip, \
((!msg->via1)||((msg)->via1->rport)||((msg)->msg_flags&FL_FORCE_RPORT))? \
(msg)->rcv.src_port: \
((msg)->via1->port)?(msg)->via1->port: SIP_PORT )
Expand All @@ -82,12 +83,13 @@ int forward_reply( struct sip_msg* msg);
* \return 0 if ok, -1 on error
*/
static inline int msg_send( struct socket_info* send_sock, int proto,
union sockaddr_union* to, unsigned int id,
const struct sockaddr_hu* to_hu, unsigned int id,
char* buf, int len, struct sip_msg* msg)
{
str out_buff;
unsigned short port;
char *ip;
const union sockaddr_union *to = &to_hu->su;

if (proto<=PROTO_NONE || proto>=PROTO_OTHER) {
LM_BUG("bogus proto %s/%d received!\n",proto2a(proto),proto);
Expand Down Expand Up @@ -120,7 +122,7 @@ static inline int msg_send( struct socket_info* send_sock, int proto,
/* update the length for further processing */
len = out_buff.len;

if (protos[proto].tran.send(send_sock, out_buff.s, out_buff.len, to,id)<0){
if (protos[proto].tran.send(send_sock, out_buff.s, out_buff.len, to_hu,id)<0){
get_su_info(to, ip, port);
LM_ERR("send() to %s:%hu for proto %s/%d failed\n",
ip, port, proto2a(proto),proto);
Expand Down
72 changes: 53 additions & 19 deletions ip_addr.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#ifndef ip_addr_h
#define ip_addr_h

#include <stddef.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
Expand All @@ -45,6 +46,8 @@

#include "dprint.h"

#define MAX_DNS_NAME 256

#define MAX_RECV_BUFFER_SIZE 256*1024
#define MAX_SEND_BUFFER_SIZE 512*1024
#define BUFFER_INCREMENT 2048
Expand Down Expand Up @@ -80,22 +83,21 @@ struct net{
struct ip_addr mask;
};

union sockaddr_union_no_hostname{
struct sockaddr s;
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
};

union sockaddr_union{
struct sockaddr s;
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
struct {
union sockaddr_union_no_hostname _padding;
char hostname[256];
} h;
};


struct sockaddr_hu{
union sockaddr_union su;
const str_const *hp;
struct {
str_const hoststr;
char hostname[MAX_DNS_NAME];
} _;
};

enum si_flags { SI_NONE=0, SI_IS_IP=1, SI_IS_LO=2, SI_IS_MCAST=4,
SI_IS_ANYCAST=8, SI_FRAG=16, SI_REUSEPORT=32 };
Expand All @@ -117,7 +119,7 @@ struct receive_info {
struct dest_info {
int proto;
unsigned int proto_reserved1; /*!< tcp stores the connection id here */
union sockaddr_union to;
struct sockaddr_hu to;
struct socket_info* send_sock;
};

Expand Down Expand Up @@ -221,7 +223,7 @@ inline static int matchnet(struct ip_addr* ip, struct net* net)


/*! \brief inits an ip_addr pointer from a sockaddr structure*/
static inline void sockaddr2ip_addr(struct ip_addr* ip, struct sockaddr* sa)
static inline void sockaddr2ip_addr(struct ip_addr* ip, const struct sockaddr* sa)
{
void *copyfrom;

Expand Down Expand Up @@ -275,7 +277,7 @@ static inline int su_cmp(union sockaddr_union* s1, union sockaddr_union* s2)


/*! \brief gets the port number (host byte order) */
static inline unsigned short su_getport(union sockaddr_union* su)
static inline unsigned short su_getport(const union sockaddr_union* su)
{
if(su==0)
return 0;
Expand Down Expand Up @@ -307,7 +309,7 @@ static inline void su_setport(union sockaddr_union* su, unsigned short port)
}

/*! \brief inits an ip_addr pointer from a sockaddr_union ip address */
static inline void su2ip_addr(struct ip_addr* ip, union sockaddr_union* su)
static inline void su2ip_addr(struct ip_addr* ip, const union sockaddr_union* su)
{
switch(su->s.sa_family){
case AF_INET:
Expand Down Expand Up @@ -369,16 +371,12 @@ static inline int init_su( union sockaddr_union* su,
* WARNING: no index overflow checks!
* \return 0 if ok, -1 on error (unknown address family) */
static inline int hostent2su( union sockaddr_union* su,
struct hostent* he,
const struct hostent* he,
unsigned int idx,
unsigned short port )
{
memset(su, 0, sizeof(union sockaddr_union)); /*needed on freebsd*/

/* copy the hostname into the sockaddr_union */
strncpy(su->h.hostname, he->h_name, sizeof(su->h.hostname)-1);
su->h.hostname[sizeof(su->h.hostname)-1] = 0;

su->s.sa_family=he->h_addrtype;
switch(he->h_addrtype){
case AF_INET6:
Expand All @@ -402,6 +400,42 @@ static inline int hostent2su( union sockaddr_union* su,
return 0;
}

static inline int hostent2hu( struct sockaddr_hu *hu,
struct hostent* he,
unsigned int idx,
unsigned short port )
{
union sockaddr_union* su = &hu->su;
size_t nlen = strlen(he->h_name);

if (nlen >= sizeof(hu->_.hostname)) {
LM_CRIT("Hostname is too long: \"%s\"", he->h_name);
return -1;
}

int r = hostent2su(su, he, idx, port);

if (r == 0) {
memcpy(hu->_.hostname, he->h_name, nlen);
hu->_.hostname[nlen] = 0;
hu->_.hoststr.s = hu->_.hostname;
hu->_.hoststr.len = nlen;
hu->hp = &hu->_.hoststr;
}
return r;
}

static inline void hu_dup(const struct sockaddr_hu *hu_s, struct sockaddr_hu *hu_d)
{
if (hu_s->hp != NULL) {
memcpy(hu_d, hu_s, sizeof(*hu_d));
hu_d->_.hoststr.s = hu_d->_.hostname;
hu_d->hp = &hu_d->_.hoststr;
} else {
memcpy(hu_d, hu_s, sizeof(*hu_d) - offsetof(struct sockaddr_hu, _));
}
}

/*! \brief maximum size of a str returned by ip_addr2a (including \\0') */
#define IP_ADDR_MAX_STR_SIZE 40 /* 1234:5678:9012:3456:7890:1234:5678:9012\0 */
#define IP_ADDR2STR_BUF_NO 4
Expand Down
2 changes: 1 addition & 1 deletion modules/cgrates/cgrates.c
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ static int cgrates_set_engine(modparam_t type, void * val)
e->port = port;

if ((ip = str2ip(&host)) || (ip = str2ip6(&host)))
init_su(&e->su, ip, port);
init_su(&e->hu.su, ip, port);
else
e->is_fqdn = 1;

Expand Down
12 changes: 6 additions & 6 deletions modules/cgrates/cgrates_engine.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ static void cgr_conn_schedule(struct cgr_conn *c)

#else /* HAVE_TIMER_FD */
#warning Your GLIB is too old, disabling cgrates async re-connect!!!
#define cgr_conn_schedule()
#define cgr_conn_schedule(...)
#endif /* HAVE_TIMER_FD */

void cgrc_conn_rpc(int sender, void *p)
Expand Down Expand Up @@ -122,8 +122,8 @@ struct cgr_conn *cgr_get_free_conn(struct cgr_engine *e)
c = list_entry(l, struct cgr_conn, list);
if (c->state == CGRC_CLOSED) {
if (c->disable_time + cgre_retry_tout < now) {
if (tcp_connect_blocking_timeout(c->fd, &c->engine->su.s,
sockaddru_len(c->engine->su), c->connect_timeout)<0){
if (tcp_connect_blocking_timeout(c->fd, &c->engine->hu.su.s,
sockaddru_len(c->engine->hu.su), c->connect_timeout)<0){
LM_INFO("cannot connect to %.*s:%d\n", c->engine->host.len,
c->engine->host.s, c->engine->port);
c->disable_time = now;
Expand Down Expand Up @@ -252,7 +252,7 @@ static int cgrc_conn(struct cgr_conn *c)

if (c->engine->is_fqdn) {
he = resolvehost(c->engine->host.s, 1);
if (!he || hostent2su(&c->engine->su, he, 0, c->engine->port) < 0) {
if (!he || hostent2hu(&c->engine->hu, he, 0, c->engine->port) < 0) {
LM_ERR("cannot resolve %.*s:%d\n", c->engine->host.len,
c->engine->host.s, c->engine->port);
return -1;
Expand All @@ -268,9 +268,9 @@ static int cgrc_conn(struct cgr_conn *c)
src_su = &_src_su;
}

tcp_con_get_profile(&c->engine->su, src_su, PROTO_TCP, &prof);
tcp_con_get_profile(&c->engine->hu.su, src_su, PROTO_TCP, &prof);

s = tcp_sync_connect_fd(src_su, &c->engine->su, PROTO_TCP, &prof, 0);
s = tcp_sync_connect_fd(src_su, &c->engine->hu, PROTO_TCP, &prof, 0);
if (s < 0) {
LM_ERR("cannot connect to %.*s:%d\n", c->engine->host.len,
c->engine->host.s, c->engine->port);
Expand Down
2 changes: 1 addition & 1 deletion modules/cgrates/cgrates_engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ struct cgr_engine {
str host;

int is_fqdn;
union sockaddr_union su;
struct sockaddr_hu hu;
time_t disable_time;

struct cgr_conn *default_con;
Expand Down
Loading

0 comments on commit cf2dad2

Please sign in to comment.