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.

Untested.
  • Loading branch information
sobomax committed Nov 29, 2023
1 parent 5ea4ec8 commit 9393038
Show file tree
Hide file tree
Showing 42 changed files with 253 additions and 185 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_su( p, &to.su, (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
65 changes: 46 additions & 19 deletions ip_addr.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,23 +80,22 @@ 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 sockaddr_hu{
union sockaddr_union su;
const str_const *hp;
struct {
union sockaddr_union_no_hostname _padding;
str_const hoststr;
char hostname[256];
} h;
} _;
};



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 +116,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 +220,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 +274,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 +306,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 @@ -368,17 +367,13 @@ static inline int init_su( union sockaddr_union* su,
* the hostent structure and a port no. (host byte order)
* 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,
static inline int hostent2su( union sockaddr_union *su,
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 +397,38 @@ 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 0;
}

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

/*! \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
15 changes: 9 additions & 6 deletions modules/clusterer/clusterer.c
Original file line number Diff line number Diff line change
Expand Up @@ -322,8 +322,9 @@ static int msg_send_retry(bin_packet_t *packet, node_info_t *dest,
}
bin_get_buffer(packet, &send_buffer);

struct sockaddr_hu to = {.su = chosen_dest->addr};
if (msg_send(chosen_dest->cluster->send_sock, chosen_dest->proto,
&chosen_dest->addr, 0, send_buffer.s, send_buffer.len, 0) < 0) {
&to, 0, send_buffer.s, send_buffer.len, 0) < 0) {
LM_ERR("msg_send() to node [%d] failed\n", chosen_dest->node_id);
retr_send = 1;

Expand Down Expand Up @@ -1474,15 +1475,17 @@ int send_single_cap_update(cluster_info_t *cluster, struct local_cap *cap,
bin_push_int(&packet, current_id);
bin_get_buffer(&packet, &bin_buffer);

for (i = 0; i < no_dests; i++)
for (i = 0; i < no_dests; i++) {
struct sockaddr_hu to = {.su = destinations[i]->addr};
if (msg_send(cluster->send_sock, destinations[i]->proto,
&destinations[i]->addr, 0, bin_buffer.s, bin_buffer.len, 0) < 0) {
&to, 0, bin_buffer.s, bin_buffer.len, 0) < 0) {
LM_ERR("Failed to send capability update to node [%d]\n",
destinations[i]->node_id);
set_link_w_neigh_adv(-1, LS_RESTART_PINGING, destinations[i]);
} else
LM_DBG("Sent capability update to node [%d]\n",
destinations[i]->node_id);
}

bin_free_packet(&packet);

Expand Down Expand Up @@ -1567,8 +1570,8 @@ int send_cap_update(node_info_t *dest_node, int require_reply)
bin_push_int(&packet, 1); /* path length is 1, only current node at this point */
bin_push_int(&packet, current_id);
bin_get_buffer(&packet, &bin_buffer);

if (msg_send(dest_node->cluster->send_sock, dest_node->proto, &dest_node->addr,
struct sockaddr_hu to = {.su = dest_node->addr};
if (msg_send(dest_node->cluster->send_sock, dest_node->proto, &to,
0, bin_buffer.s, bin_buffer.len, 0) < 0) {
LM_ERR("Failed to send capability update to node [%d]\n", dest_node->node_id);
set_link_w_neigh_adv(-1, LS_RESTART_PINGING, dest_node);
Expand Down Expand Up @@ -1851,4 +1854,4 @@ unsigned long clusterer_get_num_nodes(int state)
lock_stop_read(cl_list_lock);

return nodecount;
}
}
Loading

0 comments on commit 9393038

Please sign in to comment.