oceanbase

Форк
0
/
easy_inet.c 
287 строк · 6.8 Кб
1
#include "util/easy_inet.h"
2
#include "util/easy_string.h"
3
#include <easy_atomic.h>
4
#include <netinet/in.h>
5
#include <netinet/tcp.h>
6
#include <netdb.h>
7
#include <arpa/inet.h>      // inet_addr
8
#include <sys/ioctl.h>
9
#include <linux/if.h>
10

11
/**
12
 * 把sockaddr_in转成string
13
 */
14
char *easy_inet_addr_to_str(easy_addr_t *addr, char *buffer, int len)
15
{
16
    unsigned char           *b;
17

18
    if (addr->family == AF_INET6) {
19
        char                    tmp[INET6_ADDRSTRLEN];
20

21
        if (inet_ntop(AF_INET6, addr->u.addr6, tmp, INET6_ADDRSTRLEN) != NULL) {
22
            if (addr->port) {
23
                lnprintf(buffer, len, "[%s]:%d", tmp, ntohs(addr->port));
24
            } else {
25
                lnprintf(buffer, len, "%s", tmp);
26
            }
27
        }
28
    } else {
29
        b = (unsigned char *) &addr->u.addr;
30

31
        if (addr->port)
32
            lnprintf(buffer, len, "%d.%d.%d.%d:%d", b[0], b[1], b[2], b[3], ntohs(addr->port));
33
        else
34
            lnprintf(buffer, len, "%d.%d.%d.%d", b[0], b[1], b[2], b[3]);
35
    }
36

37
    return buffer;
38
}
39

40
/**
41
 * 把str转成addr(用uint64_t表示,IPV4)
42
 */
43
easy_addr_t easy_inet_str_to_addr(const char *host, int port)
44
{
45
    easy_addr_t             address;
46
    char                    *p, buffer[64];
47
    int                     len = -1, ipv6 = 0;
48

49
    memset(&address, 0, sizeof(easy_addr_t));
50

51
    if (host) {
52
        if (*host == '[' && (p = strchr(host, ']')) != NULL) {
53
            host ++;
54
            len = p - host;
55
            p = (*(p + 1) == ':') ? (p + 2) : NULL;
56
            ipv6 = 0x10000;
57
        } else if ((p = strchr(host, ':')) != NULL && (p == strrchr(host, ':'))) {
58
            len = p - host;
59
            p ++;
60
        }
61

62
        if (len > 63)
63
            return address;
64

65
        if (len >= 0) {
66
            memcpy(buffer, host, len);
67
            buffer[len] = '\0';
68
            host = buffer;
69

70
            if (!port && p) port = atoi(p);
71
        }
72
    }
73

74
    // parse host
75
    easy_inet_parse_host(&address, host, (port | ipv6));
76

77
    return address;
78
}
79

80
/**
81
 * 把端口改变一下
82
 */
83
easy_addr_t easy_inet_add_port(easy_addr_t *addr, int diff)
84
{
85
    easy_addr_t             ret;
86

87
    memcpy(&ret, addr, sizeof(easy_addr_t));
88
    ret.port = ntohs(ntohs(addr->port) + diff);
89
    return ret;
90
}
91

92
/**
93
 * 是IP地址, 如: 192.168.1.2
94
 */
95
int easy_inet_is_ipaddr(const char *host)
96
{
97
    unsigned char           c, *p;
98

99
    p = (unsigned char *)host;
100

101
    while ((c = (*p++)) != '\0') {
102
        if ((c != '.') && (c < '0' || c > '9')) {
103
            return 0;
104
        }
105
    }
106

107
    return 1;
108
}
109

110
/**
111
 * 解析host
112
 */
113
int easy_inet_parse_host(easy_addr_t *addr, const char *host, int port)
114
{
115
    int                     family = AF_INET;
116

117
    memset(addr, 0, sizeof(easy_addr_t));
118

119
    if (host && host[0]) {
120
        int                     rc;
121

122
        if (easy_inet_is_ipaddr(host)) {
123
            if ((rc = inet_addr(host)) == INADDR_NONE) {
124
                return EASY_ERROR;
125
            }
126

127
            addr->u.addr = rc;
128
        } else if (inet_pton(AF_INET6, host, addr->u.addr6) > 0) {
129
            family = AF_INET6;
130
        } else {
131
            // FIXME: gethostbyname会阻塞
132
            char                    buffer[1024];
133
            struct  hostent         h, *hp;
134

135
            if (gethostbyname_r(host, &h, buffer, 1024, &hp, &rc) || hp == NULL)
136
                return EASY_ERROR;
137

138
            if (hp->h_addrtype == AF_INET6) {
139
                family = AF_INET6;
140
                memcpy(addr->u.addr6, hp->h_addr, sizeof(addr->u.addr6));
141
            } else {
142
                addr->u.addr = *((uint32_t *)(hp->h_addr));
143
            }
144
        }
145
    } else if ((port & 0x10000)) {
146
        family = AF_INET6;
147
    } else {
148
        addr->u.addr = htonl(INADDR_ANY);
149
    }
150

151
    addr->family = family;
152
    addr->port = htons((port & 0xffff));
153

154
    return EASY_OK;
155
}
156

157
/**
158
 * 得到本机所有IP
159
 */
160
int easy_inet_hostaddr(uint64_t *address, int size, int local)
161
{
162
    int                     fd, ret, n;
163
    struct ifconf           ifc;
164
    struct ifreq            *ifr;
165

166
    ret = 0;
167

168
    if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
169
        return 0;
170

171
    ifc.ifc_len = sizeof(struct ifreq) * easy_max(size, 16);
172
    ifc.ifc_buf = (char *) malloc(ifc.ifc_len);
173

174
    if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0)
175
        goto out;
176

177
    ifr = ifc.ifc_req;
178

179
    for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq)) {
180
        if (local || strncmp(ifr->ifr_name, "lo", 2)) {
181
            memcpy(&address[ret++], &(ifr->ifr_addr), sizeof(uint64_t));
182
        }
183

184
        ifr++;
185
    }
186

187
out:
188
    easy_free(ifc.ifc_buf);
189
    close(fd);
190
    return ret;
191
}
192

193
/**
194
 * 根据默认路由,得到本机IP
195
 */
196
int easy_inet_myip(easy_addr_t *addr)
197
{
198
    int             fd;
199
    socklen_t       addrlen = sizeof(easy_addr_t);
200

201
    memset(addr, 0, addrlen);
202
    addr->family = AF_INET;
203
    addr->port = 17152;
204
    addr->u.addr = 1481263425;
205

206
    if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
207
        goto error_exit;
208

209
    if (connect(fd, (struct sockaddr *) addr, addrlen) < 0)
210
        goto error_exit;
211

212
    if (getsockname(fd, (struct sockaddr *) addr, &addrlen) < 0)
213
        goto error_exit;
214

215
    addr->port = 0;
216
    close(fd);
217
    return EASY_OK;
218

219
error_exit:
220
    addr->port = 0;
221
    addr->u.addr = 0;
222

223
    if (fd >= 0) close(fd);
224

225
    return EASY_ERROR;
226
}
227

228
/**
229
 *get fd addr
230
 */
231
easy_addr_t easy_inet_getpeername(int s)
232
{
233
    socklen_t               len;
234
    struct sockaddr_storage addr;
235
    easy_addr_t             ret;
236

237
    len = sizeof(addr);
238
    memset(&ret, 0, sizeof(easy_addr_t));
239

240
    if (getpeername(s, (struct sockaddr *) &addr, &len) == 0) {
241
        easy_inet_atoe(&addr, &ret);
242
    }
243

244
    return ret;
245
}
246

247
/**
248
 *
249
 */
250
void easy_inet_atoe(void *a, easy_addr_t *e)
251
{
252
    struct sockaddr_storage *addr = (struct sockaddr_storage *) a;
253
    memset(e, 0, sizeof(easy_addr_t));
254

255
    if (addr->ss_family == AF_UNIX) {
256
        e->family = AF_UNIX;
257
    } else if (addr->ss_family == AF_INET) {
258
        struct sockaddr_in      *s = (struct sockaddr_in *)a;
259
        e->family = AF_INET;
260
        e->port = s->sin_port;
261
        e->u.addr = s->sin_addr.s_addr;
262
    } else {
263
        struct sockaddr_in6     *s = (struct sockaddr_in6 *)a;
264
        e->family = AF_INET6;
265
        e->port = s->sin6_port;
266
        memcpy(e->u.addr6, &s->sin6_addr, sizeof(e->u.addr6));
267
    }
268
}
269

270
void easy_inet_etoa(easy_addr_t *e, void *a)
271
{
272
    if (e->family == AF_INET6) {
273
        struct sockaddr_in6     *s = (struct sockaddr_in6 *)a;
274
        s->sin6_family = AF_INET6;
275
        s->sin6_port = e->port;
276
        memcpy(&s->sin6_addr, e->u.addr6, sizeof(e->u.addr6));
277
    } else if (e->family == AF_UNIX) {
278
        struct sockaddr_un *s = (struct sockaddr_un *)a;
279
        s->sun_family = AF_UNIX;
280
        snprintf(s->sun_path, UNIX_PATH_MAX, "%s", e->u.unix_path);
281
    } else {
282
        struct sockaddr_in      *s = (struct sockaddr_in *)a;
283
        s->sin_family = AF_INET;
284
        s->sin_port = e->port;
285
        s->sin_addr.s_addr = e->u.addr;
286
    }
287
}
288

289

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.