Files
oceanbase/deps/easy/src/util/easy_inet.c
wangzelin.wzl 93a1074b0c patch 4.0
2022-10-24 17:57:12 +08:00

301 lines
7.3 KiB
C

/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
#include "util/easy_inet.h"
#include "util/easy_string.h"
#include <easy_atomic.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netdb.h>
#include <arpa/inet.h> // inet_addr
#include <sys/ioctl.h>
#include <linux/if.h>
/**
* 把sockaddr_in转成string
*/
char *easy_inet_addr_to_str(easy_addr_t *addr, char *buffer, int len)
{
unsigned char *b;
if (addr->family == AF_INET6) {
char tmp[INET6_ADDRSTRLEN];
if (inet_ntop(AF_INET6, addr->u.addr6, tmp, INET6_ADDRSTRLEN) != NULL) {
if (addr->port) {
lnprintf(buffer, len, "[%s]:%d", tmp, ntohs(addr->port));
} else {
lnprintf(buffer, len, "%s", tmp);
}
}
} else {
b = (unsigned char *) &addr->u.addr;
if (addr->port)
lnprintf(buffer, len, "%d.%d.%d.%d:%d", b[0], b[1], b[2], b[3], ntohs(addr->port));
else
lnprintf(buffer, len, "%d.%d.%d.%d", b[0], b[1], b[2], b[3]);
}
return buffer;
}
/**
* 把str转成addr(用uint64_t表示,IPV4)
*/
easy_addr_t easy_inet_str_to_addr(const char *host, int port)
{
easy_addr_t address;
char *p, buffer[64];
int len = -1, ipv6 = 0;
memset(&address, 0, sizeof(easy_addr_t));
if (host) {
if (*host == '[' && (p = strchr(host, ']')) != NULL) {
host ++;
len = p - host;
p = (*(p + 1) == ':') ? (p + 2) : NULL;
ipv6 = 0x10000;
} else if ((p = strchr(host, ':')) != NULL && (p == strrchr(host, ':'))) {
len = p - host;
p ++;
}
if (len > 63)
return address;
if (len >= 0) {
memcpy(buffer, host, len);
buffer[len] = '\0';
host = buffer;
if (!port && p) port = atoi(p);
}
}
// parse host
easy_inet_parse_host(&address, host, (port | ipv6));
return address;
}
/**
* 把端口改变一下
*/
easy_addr_t easy_inet_add_port(easy_addr_t *addr, int diff)
{
easy_addr_t ret;
memcpy(&ret, addr, sizeof(easy_addr_t));
ret.port = ntohs(ntohs(addr->port) + diff);
return ret;
}
/**
* 是IP地址, 如: 192.168.1.2
*/
int easy_inet_is_ipaddr(const char *host)
{
unsigned char c, *p;
p = (unsigned char *)host;
while ((c = (*p++)) != '\0') {
if ((c != '.') && (c < '0' || c > '9')) {
return 0;
}
}
return 1;
}
/**
* 解析host
*/
int easy_inet_parse_host(easy_addr_t *addr, const char *host, int port)
{
int family = AF_INET;
memset(addr, 0, sizeof(easy_addr_t));
if (host && host[0]) {
int rc;
if (easy_inet_is_ipaddr(host)) {
if ((rc = inet_addr(host)) == INADDR_NONE) {
return EASY_ERROR;
}
addr->u.addr = rc;
} else if (inet_pton(AF_INET6, host, addr->u.addr6) > 0) {
family = AF_INET6;
} else {
// FIXME: gethostbyname会阻塞
char buffer[1024];
struct hostent h, *hp;
if (gethostbyname_r(host, &h, buffer, 1024, &hp, &rc) || hp == NULL)
return EASY_ERROR;
if (hp->h_addrtype == AF_INET6) {
family = AF_INET6;
memcpy(addr->u.addr6, hp->h_addr, sizeof(addr->u.addr6));
} else {
addr->u.addr = *((uint32_t *)(hp->h_addr));
}
}
} else if ((port & 0x10000)) {
family = AF_INET6;
} else {
addr->u.addr = htonl(INADDR_ANY);
}
addr->family = family;
addr->port = htons((port & 0xffff));
return EASY_OK;
}
/**
* 得到本机所有IP
*/
int easy_inet_hostaddr(uint64_t *address, int size, int local)
{
int fd, ret, n;
struct ifconf ifc;
struct ifreq *ifr;
ret = 0;
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
return 0;
ifc.ifc_len = sizeof(struct ifreq) * easy_max(size, 16);
ifc.ifc_buf = (char *) malloc(ifc.ifc_len);
if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0)
goto out;
ifr = ifc.ifc_req;
for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq)) {
if (local || strncmp(ifr->ifr_name, "lo", 2)) {
memcpy(&address[ret++], &(ifr->ifr_addr), sizeof(uint64_t));
}
ifr++;
}
out:
easy_free(ifc.ifc_buf);
close(fd);
return ret;
}
/**
* 根据默认路由,得到本机IP
*/
int easy_inet_myip(easy_addr_t *addr)
{
int fd;
socklen_t addrlen = sizeof(easy_addr_t);
memset(addr, 0, addrlen);
addr->family = AF_INET;
addr->port = 17152;
addr->u.addr = 1481263425;
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
goto error_exit;
if (connect(fd, (struct sockaddr *) addr, addrlen) < 0)
goto error_exit;
if (getsockname(fd, (struct sockaddr *) addr, &addrlen) < 0)
goto error_exit;
addr->port = 0;
close(fd);
return EASY_OK;
error_exit:
addr->port = 0;
addr->u.addr = 0;
if (fd >= 0) close(fd);
return EASY_ERROR;
}
/**
*get fd addr
*/
easy_addr_t easy_inet_getpeername(int s)
{
socklen_t len;
struct sockaddr_storage addr;
easy_addr_t ret;
len = sizeof(addr);
memset(&ret, 0, sizeof(easy_addr_t));
if (getpeername(s, (struct sockaddr *) &addr, &len) == 0) {
easy_inet_atoe(&addr, &ret);
}
return ret;
}
/**
*
*/
void easy_inet_atoe(void *a, easy_addr_t *e)
{
struct sockaddr_storage *addr = (struct sockaddr_storage *) a;
memset(e, 0, sizeof(easy_addr_t));
if (addr->ss_family == AF_UNIX) {
e->family = AF_UNIX;
} else if (addr->ss_family == AF_INET) {
struct sockaddr_in *s = (struct sockaddr_in *)a;
e->family = AF_INET;
e->port = s->sin_port;
e->u.addr = s->sin_addr.s_addr;
} else {
struct sockaddr_in6 *s = (struct sockaddr_in6 *)a;
e->family = AF_INET6;
e->port = s->sin6_port;
memcpy(e->u.addr6, &s->sin6_addr, sizeof(e->u.addr6));
}
}
void easy_inet_etoa(easy_addr_t *e, void *a)
{
if (e->family == AF_INET6) {
struct sockaddr_in6 *s = (struct sockaddr_in6 *)a;
s->sin6_family = AF_INET6;
s->sin6_port = e->port;
memcpy(&s->sin6_addr, e->u.addr6, sizeof(e->u.addr6));
} else if (e->family == AF_UNIX) {
struct sockaddr_un *s = (struct sockaddr_un *)a;
s->sun_family = AF_UNIX;
snprintf(s->sun_path, UNIX_PATH_MAX, "%s", e->u.unix_path);
} else {
struct sockaddr_in *s = (struct sockaddr_in *)a;
s->sin_family = AF_INET;
s->sin_port = e->port;
s->sin_addr.s_addr = e->u.addr;
}
}