Coverage Report

Created: 2025-08-26 06:38

/src/opensips/forward.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2008-2025 OpenSIPS Project
3
 * Copyright (C) 2001-2003 FhG Fokus
4
 *
5
 * This file is part of opensips, a free SIP server.
6
 *
7
 * opensips is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 2 of the License, or
10
 * (at your option) any later version
11
 *
12
 * opensips is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21
22
/*!
23
 * \file
24
 * \brief OpenSIPS Stateless forward support
25
 */
26
27
28
#ifndef forward_h
29
#define forward_h
30
31
#include "globals.h"
32
#include "mem/mem.h"
33
#include "parser/msg_parser.h"
34
#include "route.h"
35
#include "proxy.h"
36
#include "ip_addr.h"
37
#include "script_cb.h"
38
#include "sl_cb.h"
39
#include "net/trans.h"
40
#include "socket_info.h"
41
42
const struct socket_info* get_send_socket(struct sip_msg* msg,
43
    const union sockaddr_union* su, int proto);
44
45
const struct socket_info* get_out_socket(const union sockaddr_union* to,
46
    int proto);
47
48
int check_self(str* host, unsigned short port, unsigned short proto);
49
50
/*! \brief checks if the proto:host:port is one of the address we listen on
51
 *
52
 * if port==0, the  port number is expended to default
53
 * if proto==0 (PROTO_NONE) the protocol is considered UDP
54
 * returns 1 if true, 0 if false, -1 on error
55
 */
56
#define check_self_strict( _host, _port, _proto) \
57
  check_self(_host,_port?_port:protos[_proto?_proto:PROTO_UDP].default_port,\
58
    _proto?_proto:PROTO_UDP)
59
60
int forward_request( struct sip_msg* msg,  struct proxy_l* p);
61
62
int update_sock_struct_from_via( union sockaddr_union* to,
63
   struct sip_msg* msg, struct via_body* via );
64
65
/*! \brief use src_ip, port=src_port if rport, via port if via port, 5060 otherwise */
66
#define update_sock_struct_from_ip(  to, msg ) \
67
  init_su((to), &(msg)->rcv.src_ip, \
68
      ((!msg->via1)||((msg)->via1->rport)||((msg)->msg_flags&FL_FORCE_RPORT))? \
69
              (msg)->rcv.src_port: \
70
              ((msg)->via1->port)?(msg)->via1->port: SIP_PORT )
71
72
int forward_reply( struct sip_msg* msg);
73
74
75
76
/*! \brief
77
 *
78
 *  \param send_sock = 0 if already known (e.g. for udp in some cases),
79
 *        non-0 otherwise
80
 *  \param proto =TCP|UDP
81
 *  \param to = sockaddr-like description of the destination
82
 *  \param id - only used on tcp, it will force sending on connection "id"
83
 *       if id!=0 and the connection exists, else it will send to "to"
84
 *       (useful for sending replies on  the same connection as the request
85
 *       that generated them; use 0 if you don't want this)
86
 * \param buf - the buffer containing the message to be sent
87
 * \param len - the length of the message to be sent
88
 * \return 0 if ok, -1 on error
89
 */
90
static inline int msg_send( const struct socket_info* send_sock, int proto,
91
              union sockaddr_union* to, unsigned int id,
92
              char* buf, int len, struct sip_msg* msg)
93
0
{
94
0
  str out_buff;
95
0
  unsigned short port;
96
0
  char *ip;
97
98
0
  if (proto<=PROTO_NONE || proto>=PROTO_OTHER) {
99
0
    LM_BUG("bogus proto %s/%d received!\n",proto2a(proto),proto);
100
0
    return -1;
101
0
  }
102
0
  if (protos[proto].id==PROTO_NONE) {
103
0
    LM_ERR("trying to using proto %s/%d which is not initialized!\n",
104
0
      proto2a(proto),proto);
105
0
    return -1;
106
0
  }
107
108
0
  out_buff.len = len;
109
0
  out_buff.s = buf;
110
111
  /* determine the send socket */
112
0
  if (send_sock==0)
113
0
    send_sock=get_send_socket(0, to, proto);
114
0
  if (send_sock==0){
115
0
    LM_ERR("no sending socket found for proto %s/%d\n",
116
0
      proto2a(proto), proto);
117
0
    goto error;
118
0
  }
119
120
  /* the raw processing callbacks are free to change whatever inside
121
   * the buffer further use out_buff.s and at the end try to free out_buff.s
122
   * if changed by callbacks */
123
0
  if ( is_sip_proto(proto) )
124
0
    run_post_raw_processing_cb(POST_RAW_PROCESSING,&out_buff, msg);
125
126
  /* update the length for further processing */
127
0
  len = out_buff.len;
128
0
  if ((send_sock->flags & SI_INTERNAL) && send_sock->internal_proto != PROTO_NONE)
129
0
    proto = send_sock->internal_proto;
130
131
0
  if (protos[proto].tran.send(send_sock, out_buff.s, out_buff.len, to,id)<0){
132
0
    get_su_info(to, ip, port);
133
0
    LM_ERR("send() to %s:%hu for proto %s/%d failed\n",
134
0
        ip, port, proto2a(proto),proto);
135
0
    goto error;
136
0
  }
137
138
  /* potentially allocated by the out raw processing */
139
0
  if (out_buff.s != buf)
140
0
    pkg_free(out_buff.s);
141
142
0
  return 0;
143
0
error:
144
0
  if (out_buff.s != buf)
145
0
    pkg_free(out_buff.s);
146
0
  return -1;
147
0
}
Unexecuted instantiation: route.c:msg_send
Unexecuted instantiation: receive.c:msg_send
Unexecuted instantiation: forward.c:msg_send
Unexecuted instantiation: core_cmds.c:msg_send
148
149
150
#endif