Coverage Report

Created: 2026-10-17 06:23

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensips/forward.h
Line
Count
Source
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/net_tcp.h"
40
#include "net/trans.h"
41
#include "socket_info.h"
42
43
const struct socket_info* get_send_socket(struct sip_msg* msg,
44
    const union sockaddr_union* su, int proto);
45
46
const struct socket_info* get_out_socket(const union sockaddr_union* to,
47
    int proto);
48
49
int check_self(str* host, unsigned short port, unsigned short proto);
50
51
/*! \brief checks if the proto:host:port is one of the address we listen on
52
 *
53
 * if port==0, the  port number is expended to default
54
 * if proto==0 (PROTO_NONE) the protocol is considered UDP
55
 * returns 1 if true, 0 if false, -1 on error
56
 */
57
#define check_self_strict( _host, _port, _proto) \
58
  check_self(_host,_port?_port:protos[_proto?_proto:PROTO_UDP].default_port,\
59
    _proto?_proto:PROTO_UDP)
60
61
int forward_request( struct sip_msg* msg,  struct proxy_l* p);
62
63
int update_sock_struct_from_via( union sockaddr_union* to,
64
   struct sip_msg* msg, struct via_body* via );
65
66
/*! \brief use src_ip, port=src_port if rport, via port if via port, 5060 otherwise */
67
#define update_sock_struct_from_ip(  to, msg ) \
68
  init_su((to), &(msg)->rcv.src_ip, \
69
      ((!msg->via1)||((msg)->via1->rport)||((msg)->msg_flags&FL_FORCE_RPORT))? \
70
              (msg)->rcv.src_port: \
71
              ((msg)->via1->port)?(msg)->via1->port: SIP_PORT )
72
73
int forward_reply( struct sip_msg* msg);
74
75
76
77
/*! \brief
78
 *
79
 *  \param send_sock = 0 if already known (e.g. for udp in some cases),
80
 *        non-0 otherwise
81
 *  \param proto =TCP|UDP
82
 *  \param to = sockaddr-like description of the destination
83
 *  \param id - only used on tcp, it will force sending on connection "id"
84
 *       if id!=0 and the connection exists, else it will send to "to"
85
 *       (useful for sending replies on  the same connection as the request
86
 *       that generated them; use 0 if you don't want this)
87
 * \param buf - the buffer containing the message to be sent
88
 * \param len - the length of the message to be sent
89
 * \return 0 if ok, -1 on error
90
 */
91
static inline int msg_send( const struct socket_info* send_sock, int proto,
92
              union sockaddr_union* to, unsigned int id,
93
              char* buf, int len, struct sip_msg* msg)
94
0
{
95
0
  str out_buff;
96
0
  unsigned short port;
97
0
  char *ip;
98
99
0
  if (proto<=PROTO_NONE || proto>=PROTO_OTHER) {
100
0
    LM_BUG("bogus proto %s/%d received!\n",proto2a(proto),proto);
101
0
    return -1;
102
0
  }
103
0
  if (protos[proto].id==PROTO_NONE) {
104
0
    LM_ERR("trying to using proto %s/%d which is not initialized!\n",
105
0
      proto2a(proto),proto);
106
0
    return -1;
107
0
  }
108
109
0
  out_buff.len = len;
110
0
  out_buff.s = buf;
111
112
  /* determine the send socket */
113
0
  if (send_sock==0)
114
0
    send_sock=get_send_socket(0, to, proto);
115
0
  if (send_sock==0){
116
0
    LM_ERR("no sending socket found for proto %s/%d\n",
117
0
      proto2a(proto), proto);
118
0
    goto error;
119
0
  }
120
121
  /* the raw processing callbacks are free to change whatever inside
122
   * the buffer further use out_buff.s and at the end try to free out_buff.s
123
   * if changed by callbacks */
124
0
  if ( is_sip_proto(proto) )
125
0
    run_post_raw_processing_cb(POST_RAW_PROCESSING,&out_buff, msg);
126
127
  /* update the length for further processing */
128
0
  len = out_buff.len;
129
0
  if ((send_sock->flags & SI_INTERNAL) && send_sock->internal_proto != PROTO_NONE)
130
0
    proto = send_sock->internal_proto;
131
132
0
  if (is_tcp_based_proto(proto)) {
133
0
    last_outgoing_tcp_id = 0;
134
0
    if (send_sock->last_real_ports) {
135
0
      send_sock->last_real_ports->local = 0;
136
0
      send_sock->last_real_ports->remote = 0;
137
0
    }
138
0
  }
139
140
0
  if (protos[proto].tran.send(send_sock, out_buff.s, out_buff.len, to, id,
141
0
      msg) < 0){
142
0
    get_su_info(to, ip, port);
143
0
    LM_ERR("send() to %s:%hu for proto %s/%d failed\n",
144
0
        ip, port, proto2a(proto),proto);
145
0
    goto error;
146
0
  }
147
148
  /* potentially allocated by the out raw processing */
149
0
  if (out_buff.s != buf)
150
0
    pkg_free(out_buff.s);
151
152
0
  return 0;
153
0
error:
154
0
  if (out_buff.s != buf)
155
0
    pkg_free(out_buff.s);
156
0
  return -1;
157
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
158
159
160
#endif