Project

General

Profile

Bug #4692 » SAT-IP-Print-external-NAT-ip-and-port-v2.diff

Patch version 2 - Mono Polimorph, 2017-11-20 22:09

View differences:

src/satip/rtsp.c
92 92
static void rtsp_close_session(session_t *rs);
93 93
static void rtsp_free_session(session_t *rs);
94 94

  
95
static char any_ip[] = "127.0.0.1\0";
95 96

  
96 97
/*
97 98
 *
......
319 320
/*
320 321
 *
321 322
 */
323
static inline int
324
rtsp_announced_port(struct sockaddr_storage *peer, struct sockaddr_storage *self)
325
{
326
  int used_port = 0;
327

  
328
  if (satip_server_conf.satip_nat_name_force || !check_is_local_address(peer,self)) {
329
    used_port = (rtsp_nat_port > 0)? rtsp_nat_port : rtsp_port;
330
  } else {
331
    used_port = rtsp_port;
332
  }
333

  
334
  return used_port;
335
}
336

  
337
/*
338
 *
339
 */
340
static inline char *
341
rtsp_announced_ip(struct sockaddr_storage *peer, struct sockaddr_storage *self)
342
{
343
  char *used_ip;
344

  
345
  if (satip_server_conf.satip_nat_name_force || !check_is_local_address(peer,self)) {
346
    used_ip = rtsp_nat_ip;
347
  } else {
348
    used_ip = rtsp_ip;
349
  }
350

  
351
  if (used_ip[0] == '*' || used_ip[0] == '\0' || used_ip == NULL) {
352
    used_ip = any_ip;
353
  }
354

  
355
  return used_ip;
356
}
357

  
358
/*
359
 *
360
 */
322 361
static void
323 362
rtsp_slave_add
324 363
  (session_t *rs, mpegts_service_t *master, mpegts_service_t *slave)
......
1322 1361
  char *u = tvh_strdupa(hc->hc_url);
1323 1362
  session_t *rs;
1324 1363
  htsbuf_queue_t q;
1325
  char buf[96];
1364
  char buf[96], *used_ip = NULL;
1326 1365
  int r = HTTP_STATUS_BAD_REQUEST;
1327
  int stream, first = 1, valid;
1366
  int stream, first = 1, valid, used_port;
1328 1367

  
1329 1368
  htsbuf_queue_init(&q, 0);
1330 1369

  
......
1381 1420
  http_arg_init(&args);
1382 1421
  if (hc->hc_session)
1383 1422
    http_arg_set(&args, "Session", hc->hc_session);
1384
  if (stream > 0)
1385
    snprintf(buf, sizeof(buf), "rtsp://%s/stream=%i", rtsp_ip, stream);
1423
  used_port = rtsp_announced_port(hc->hc_peer,hc->hc_self);
1424
  used_ip = rtsp_announced_ip(hc->hc_peer,hc->hc_self);
1425
  if ((stream > 0) && (used_port != 554))
1426
    snprintf(buf, sizeof(buf), "rtsp://%s:%d/stream=%i", used_ip, used_port, stream);
1427
  else if ((stream > 0) && (used_port == 554))
1428
    snprintf(buf, sizeof(buf), "rtsp://%s/stream=%i", used_ip, stream);
1429
  else if (used_port != 554)
1430
    snprintf(buf, sizeof(buf), "rtsp://%s:%d", used_ip, used_port);
1386 1431
  else
1387
    snprintf(buf, sizeof(buf), "rtsp://%s", rtsp_ip);
1432
    snprintf(buf, sizeof(buf), "rtsp://%s", used_ip);
1388 1433
  http_arg_set(&args, "Content-Base", buf);
1389 1434
  http_send_begin(hc);
1390 1435
  http_send_header(hc, HTTP_STATUS_OK, "application/sdp", q.hq_size,
......
1408 1453
rtsp_process_play(http_connection_t *hc, int cmd)
1409 1454
{
1410 1455
  session_t *rs;
1411
  int errcode = HTTP_STATUS_BAD_REQUEST, valid = 0, i, stream;
1412
  char buf[256], *u = tvh_strdupa(hc->hc_url);
1456
  int errcode = HTTP_STATUS_BAD_REQUEST, valid = 0, i, stream, used_port;
1457
  char buf[256], *u = tvh_strdupa(hc->hc_url), *used_ip = NULL;
1413 1458
  http_arg_list_t args;
1414 1459

  
1415 1460
  http_arg_init(&args);
......
1467 1512
    snprintf(buf, sizeof(buf), "%d", rs->stream);
1468 1513
    http_arg_set(&args, "com.ses.streamID", buf);
1469 1514
  } else {
1470
    if (rtsp_port != 554)
1471
      snprintf(buf, sizeof(buf), "url=rtsp://%s:%d/stream=%d", rtsp_ip, rtsp_port, rs->stream);
1515
    used_port = rtsp_announced_port(hc->hc_peer,hc->hc_self);
1516
    used_ip = rtsp_announced_ip(hc->hc_peer,hc->hc_self);
1517
    if (used_port != 554)
1518
      snprintf(buf, sizeof(buf), "url=rtsp://%s:%d/stream=%d", used_ip, used_port, rs->stream);
1472 1519
    else
1473
      snprintf(buf, sizeof(buf), "url=rtsp://%s/stream=%d", rtsp_ip, rs->stream);
1520
      snprintf(buf, sizeof(buf), "url=rtsp://%s/stream=%d", used_ip, rs->stream);
1474 1521
    http_arg_set(&args, "RTP-Info", buf);
1475 1522
  }
1476 1523

  
src/satip/server.c
777 777
      .group  = 2,
778 778
    },
779 779
    {
780
      .type   = PT_BOOL,
781
      .id     = "satip_nat_name_force",
782
      .name   = N_("Force RTSP announcement of the external (NAT) ip:port"),
783
      .desc   = N_("Advertise only NAT address and port in RTSP commands,"
784
                   "even for local connections."),
785
      .off    = offsetof(struct satip_server_conf, satip_nat_name_force),
786
      .opts   = PO_EXPERT,
787
      .group  = 2,
788
    },
789

  
790

  
791

  
792
    {
780 793
      .type   = PT_U32,
781 794
      .id     = "satip_iptv_sig_level",
782 795
      .name   = N_("IPTV signal level"),
src/satip/server.h
65 65
  int satip_atsc_c;
66 66
  char *satip_nat_ip;
67 67
  int satip_nat_rtsp;
68
  int satip_nat_name_force;
68 69
};
69 70

  
70 71
extern struct satip_server_conf satip_server_conf;
src/tcp.c
34 34
#include <netinet/in.h>
35 35
#include <netinet/tcp.h>
36 36
#include <arpa/inet.h>
37
#include <sys/types.h>
38
#include <ifaddrs.h>
37 39

  
38 40
#include "tvheadend.h"
39 41
#include "tcp.h"
......
73 75
/**
74 76
 *
75 77
 */
78
inline int
79
check_equal_v4(const struct in_addr * a,
80
               const struct in_addr * b)
81
{
82
  return (a->s_addr == b->s_addr);
83
}
84

  
85
/**
86
 *
87
 */
88
inline int
89
check_equal_v6(const struct in6_addr * a,
90
               const struct in6_addr * b)
91
{
92
  return (memcmp(a->s6_addr, b->s6_addr, 16) == 0) ? 1 : 0;
93
}
94

  
95
/**
96
 *
97
 */
98
inline int
99
check_in_network_v4(const struct in_addr * network,
100
                    const struct in_addr * mask,
101
                    const struct in_addr * address)
102
{
103
  return ((address->s_addr & mask->s_addr) == (network->s_addr & mask->s_addr));
104
}
105

  
106
/**
107
 *
108
 */
109
inline int
110
check_in_network_v6(const struct in6_addr * network,
111
                    const struct in6_addr * mask,
112
                    const struct in6_addr * address)
113
{
114
  unsigned int i;
115
  for (i=0; i<sizeof(struct in6_addr)/sizeof (int); i++)
116
    if ( ((((int *) address)[i] & ((int *) mask)[i])) !=
117
          (((int *) network)[i] & ((int *) mask)[i])) {
118
      return 0;
119
    }
120
  return 1;
121
}
122

  
123
/**
124
 *
125
 */
126
inline int
127
check_is_any_v4(const struct in_addr * address)
128
{
129
  return (address->s_addr == INADDR_ANY);
130
}
131

  
132
/**
133
 *
134
 */
135
inline int
136
check_is_any_v6(const struct in6_addr * address)
137
{
138
  return (check_equal_v6(address,&in6addr_any));
139
}
140

  
141
/**
142
 *
143
 */
144
int
145
check_is_local_address(const struct sockaddr_storage *peer, const struct sockaddr_storage *local)
146
{
147
  struct ifaddrs *iflist, *ifdev = NULL;
148
  struct sockaddr_storage *ifaddr, *ifnetmask;
149
  int any_address = 0;
150

  
151
  if ( (local->ss_family == AF_INET  && check_is_any_v4(&((struct sockaddr_in *)local)->sin_addr) ) ||
152
       (local->ss_family == AF_INET6 && check_is_any_v6(&((struct sockaddr_in6 *)local)->sin6_addr) ) ) {
153
     any_address = 1;
154
  }
155
  tvhdebug(LS_SATIPS, "tcp_is_local_address(): ANY=%i",any_address);
156

  
157
  // Note: Not all platforms have getifaddrs()
158
  //       See http://docs.freeswitch.org/switch__utils_8c_source.html
159
  if (!local || !peer || getifaddrs(&iflist) < 0) return 0;
160

  
161
  for (ifdev = iflist; ifdev; ifdev = ifdev->ifa_next) {
162
    ifaddr = (struct sockaddr_storage *)(ifdev->ifa_addr);
163
    ifnetmask = (struct sockaddr_storage *)(ifdev->ifa_netmask);
164

  
165
    if (ifaddr && ifnetmask && ifaddr->ss_family == local->ss_family && ifaddr->ss_family == peer->ss_family) {
166

  
167
      if (ifaddr->ss_family == AF_INET) {
168
        if ((any_address || check_equal_v4( &((struct sockaddr_in *)ifaddr)->sin_addr, &((struct sockaddr_in *)local)->sin_addr ))
169
            && check_in_network_v4( &((struct sockaddr_in *)ifaddr)->sin_addr,
170
                                    &((struct sockaddr_in *)ifnetmask)->sin_addr,
171
                                    &((struct sockaddr_in *)peer)->sin_addr) ) {
172
          freeifaddrs(iflist);
173
          return 1;
174
        }
175
      } else if (ifaddr->ss_family == AF_INET6) {
176
        if ((any_address || check_equal_v6( &((struct sockaddr_in6 *)ifaddr)->sin6_addr, &((struct sockaddr_in6 *)local)->sin6_addr ))
177
            && check_in_network_v6( &((struct sockaddr_in6 *)ifaddr)->sin6_addr,
178
                                    &((struct sockaddr_in6 *)ifnetmask)->sin6_addr,
179
                                    &((struct sockaddr_in6 *)peer)->sin6_addr) ) {
180
          freeifaddrs(iflist);
181
          return 1;
182
        }
183
      }
184
    }
185
  }
186
  freeifaddrs(iflist);
187
  return 0;
188
}
189

  
190
/**
191
 *
192
 */
76 193
int
77 194
tcp_connect(const char *hostname, int port, const char *bindaddr,
78 195
            char *errbuf, size_t errbufsize, int timeout)
src/tcp.h
58 58
void tcp_server_init(void);
59 59
void tcp_server_done(void);
60 60

  
61
int check_equal_v4(const struct in_addr * a, const struct in_addr * b);
62
int check_equal_v6(const struct in6_addr * a, const struct in6_addr * b);
63
int check_in_network_v4(const struct in_addr * network,
64
                    const struct in_addr * mask,
65
                    const struct in_addr * address);
66
int check_in_network_v6(const struct in6_addr * network,
67
                    const struct in6_addr * mask,
68
                    const struct in6_addr * address);
69
int check_is_any_v4(const struct in_addr * address);
70
int check_is_any_v6(const struct in6_addr * address);
71
int check_is_local_address(const struct sockaddr_storage *peer, const struct sockaddr_storage *local);
72

  
61 73
int socket_set_dscp(int sockfd, uint32_t dscp, char *errbuf, size_t errbufsize);
62 74

  
63 75
int tcp_connect(const char *hostname, int port, const char *bindaddr,
(2-2/3)