forked from aligungr/UERANSIM
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbinder.cpp
113 lines (93 loc) · 3.47 KB
/
binder.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
//
// This file is a part of UERANSIM open source project.
// Copyright (c) 2021 ALİ GÜNGÖR.
//
// The software and all associated files are licensed under GPL-3.0
// and subject to the terms and conditions defined in LICENSE file.
//
#include <cerrno>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <arpa/inet.h>
#include <dlfcn.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
int (*real_socket)(int, int, int);
int (*real_setsockopt)(int, int, int, const void *, socklen_t);
int (*real_bind)(int, const struct sockaddr *, socklen_t);
int (*real_connect)(int, const struct sockaddr *, socklen_t);
char *bind_addr_env;
unsigned long int bind_addr_saddr;
unsigned long int inaddr_any_saddr;
struct sockaddr_in local_sockaddr_in[1];
extern "C" void _init(void)
{
const char *err;
real_socket = reinterpret_cast<int (*)(int, int, int)>(dlsym(RTLD_NEXT, "socket"));
if ((err = dlerror()) != nullptr)
{
fprintf(stderr, "dlsym (socket): %s\n", err);
}
real_setsockopt = reinterpret_cast<int (*)(int, int, int, const void *, socklen_t)>(dlsym(RTLD_NEXT, "setsockopt"));
if ((err = dlerror()) != nullptr)
{
fprintf(stderr, "dlsym (setsockopt): %s\n", err);
}
real_bind = reinterpret_cast<int (*)(int, const struct sockaddr *, socklen_t)>(dlsym(RTLD_NEXT, "bind"));
if ((err = dlerror()) != nullptr)
{
fprintf(stderr, "dlsym (bind): %s\n", err);
}
real_connect = reinterpret_cast<int (*)(int, const struct sockaddr *, socklen_t)>(dlsym(RTLD_NEXT, "connect"));
if ((err = dlerror()) != nullptr)
{
fprintf(stderr, "dlsym (connect): %s\n", err);
}
inaddr_any_saddr = htonl(INADDR_ANY);
bind_addr_env = getenv("UE_BIND_ADDR");
if (bind_addr_env)
{
bind_addr_saddr = inet_addr(bind_addr_env);
local_sockaddr_in->sin_family = AF_INET;
local_sockaddr_in->sin_addr.s_addr = bind_addr_saddr;
local_sockaddr_in->sin_port = htons(0);
}
}
extern "C" int socket(int domain, int type, int protocol)
{
return real_socket(domain, type, protocol);
}
extern "C" int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen)
{
return real_setsockopt(sockfd, level, optname, optval, optlen);
}
extern "C" int bind(int fd, const struct sockaddr *sk, socklen_t sl)
{
static struct sockaddr_in *lsk_in;
lsk_in = (struct sockaddr_in *)sk;
if ((lsk_in->sin_family == AF_INET) && (lsk_in->sin_addr.s_addr == inaddr_any_saddr) && (bind_addr_env))
{
lsk_in->sin_addr.s_addr = bind_addr_saddr;
}
return real_bind(fd, sk, sl);
}
extern "C" int connect(int fd, const struct sockaddr *sk, socklen_t sl)
{
static struct sockaddr_in *rsk_in;
rsk_in = (struct sockaddr_in *)sk;
if ((rsk_in->sin_family == AF_INET) && (bind_addr_env))
{
// HACK: DNS sorgusunu 127.0.0.53'e yaptığından eğer DNS sorgusu yapılıyorsa source IP değiştirmiyoruz.
// 127.0.0.53'in hex karşılığı: 0x3500007F (big endian)
// LATER NOTE: Aslında bunu DNS için değil genel olarak loopback'lerin hepsi için yapmak gerekir.
// Belki de rotalamada linux üzerinden ayar yapılırken specify ediliyordur. Bu kısma gerek
// kalmayabilir.
if (rsk_in->sin_addr.s_addr != 0x3500007F)
{
real_bind(fd, (struct sockaddr *)local_sockaddr_in, sizeof(struct sockaddr));
}
}
return real_connect(fd, sk, sl);
}