forked from acouzens/open5gs
net_tun library is updated for supporting FreeBSD and MacOSX
In FreeBSD and MacOSX, tun driver is automatically configured.
This commit is contained in:
parent
86908cdbe9
commit
b8a37b0ea1
|
@ -263,12 +263,10 @@ CORE_DECLARE(int) net_unregister_link(net_link_t *net_link);
|
||||||
CORE_DECLARE(int) net_fds_read_run(long timeout);
|
CORE_DECLARE(int) net_fds_read_run(long timeout);
|
||||||
|
|
||||||
/** TunTap interface */
|
/** TunTap interface */
|
||||||
CORE_DECLARE(int) net_tuntap_open(net_link_t **net_link, char *tuntap_dev_name,
|
CORE_DECLARE(int) net_tun_open(net_link_t **net_link, char *name, int is_tap);
|
||||||
int is_tap);
|
CORE_DECLARE(int) net_tun_set_ipv4(
|
||||||
|
net_link_t *net_link, c_uint32_t addr, c_uint8_t bits);
|
||||||
CORE_DECLARE(int) net_tuntap_set_ipv4(c_uint32_t ip_addr, c_uint8_t bits);
|
CORE_DECLARE(int) net_tun_close(net_link_t *net_link);
|
||||||
|
|
||||||
CORE_DECLARE(int) net_tuntap_close(net_link_t *net_link);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -1171,6 +1171,7 @@ int net_raw_open(net_link_t **net_link, int proto)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Create tuntap socket */
|
/** Create tuntap socket */
|
||||||
|
#if 0 /* deprecated */
|
||||||
int net_tuntap_open(net_link_t **net_link, char *tuntap_dev_name,
|
int net_tuntap_open(net_link_t **net_link, char *tuntap_dev_name,
|
||||||
int is_tap)
|
int is_tap)
|
||||||
{
|
{
|
||||||
|
@ -1224,35 +1225,96 @@ cleanup:
|
||||||
return -1;
|
return -1;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int net_tuntap_set_ipv4(c_uint32_t ip_addr, c_uint8_t bits)
|
/** Create tun socket */
|
||||||
|
int net_tun_open(net_link_t **net_link, char *ifname, int is_tap)
|
||||||
{
|
{
|
||||||
|
int sock;
|
||||||
|
net_link_t *new_link = NULL;
|
||||||
#if LINUX == 1
|
#if LINUX == 1
|
||||||
/* No root priviledge */
|
char *dev = "/dev/net/tun";
|
||||||
|
int rc;
|
||||||
|
struct ifreq ifr;
|
||||||
|
int flags = IFF_NO_PI;
|
||||||
|
|
||||||
|
sock = open(dev, O_RDWR);
|
||||||
|
if (sock < 0)
|
||||||
|
{
|
||||||
|
d_error("Can not open %s",dev);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
char name[C_PATH_MAX];
|
||||||
|
int tun = 0;
|
||||||
|
|
||||||
|
#define TUNTAP_ID_MAX 255
|
||||||
|
for (tun = 0; tun < TUNTAP_ID_MAX; tun++)
|
||||||
|
{
|
||||||
|
(void)snprintf(name, sizeof(name), "/dev/tun%i", tun);
|
||||||
|
if ((sock = open(name, O_RDWR)) > 0)
|
||||||
|
{
|
||||||
|
(void)snprintf(name, sizeof(name), "tun%i", tun);
|
||||||
|
ifname = name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pool_alloc_node(&link_pool, &new_link);
|
||||||
|
d_assert(new_link != NULL, return -1,"No link pool is availabe\n");
|
||||||
|
|
||||||
|
#if LINUX == 1
|
||||||
|
memset(&ifr, 0, sizeof(ifr));
|
||||||
|
|
||||||
|
ifr.ifr_flags = (is_tap ? (flags | IFF_TAP) : (flags | IFF_TUN));
|
||||||
|
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
|
||||||
|
|
||||||
|
rc = ioctl(sock, TUNSETIFF, (void *)&ifr);
|
||||||
|
if (rc < 0)
|
||||||
|
{
|
||||||
|
d_error("iotcl error(dev:%s flags = %d)", ifname, flags);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Save socket descriptor */
|
||||||
|
new_link->fd = sock;
|
||||||
|
/* Save the interface name */
|
||||||
|
strncpy(new_link->ifname, ifname, IFNAMSIZ);
|
||||||
|
|
||||||
|
*net_link = new_link;
|
||||||
return 0;
|
return 0;
|
||||||
#elif defined(DARWIN)
|
|
||||||
|
#if LINUX == 1
|
||||||
|
cleanup:
|
||||||
|
pool_free_node(&link_pool, new_link);
|
||||||
|
close(sock);
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int net_tun_set_ipv4(net_link_t *link, c_uint32_t ip_addr, c_uint8_t bits)
|
||||||
|
{
|
||||||
|
#if LINUX != 1
|
||||||
c_uint32_t mask_addr = htonl(0xffffffff << (32 - bits));
|
c_uint32_t mask_addr = htonl(0xffffffff << (32 - bits));
|
||||||
int sock = socket(AF_INET, SOCK_DGRAM, 0);
|
int sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
|
||||||
char *dev = "tun0";
|
|
||||||
struct ifaliasreq ifa;
|
struct ifaliasreq ifa;
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
struct sockaddr_in mask;
|
struct sockaddr_in mask;
|
||||||
|
|
||||||
(void)memset(&ifa, '\0', sizeof ifa);
|
(void)memset(&ifa, '\0', sizeof ifa);
|
||||||
(void)strlcpy(ifa.ifra_name, dev, sizeof ifa.ifra_name);
|
(void)strlcpy(ifa.ifra_name, link->ifname, sizeof ifa.ifra_name);
|
||||||
|
|
||||||
(void)memset(&ifr, '\0', sizeof ifr);
|
(void)memset(&ifr, '\0', sizeof ifr);
|
||||||
(void)strlcpy(ifr.ifr_name, dev, sizeof ifr.ifr_name);
|
(void)strlcpy(ifr.ifr_name, link->ifname, sizeof ifr.ifr_name);
|
||||||
|
|
||||||
/* Delete previously assigned address */
|
/* Delete previously assigned address */
|
||||||
(void)ioctl(sock, SIOCDIFADDR, &ifr);
|
(void)ioctl(sock, SIOCDIFADDR, &ifr);
|
||||||
|
|
||||||
/*
|
#if defined(DARWIN)
|
||||||
* Fill-in the destination address and netmask,
|
|
||||||
* but don't care of the broadcast address
|
|
||||||
*/
|
|
||||||
(void)memset(&addr, '\0', sizeof addr);
|
(void)memset(&addr, '\0', sizeof addr);
|
||||||
addr.sin_family = AF_INET;
|
addr.sin_family = AF_INET;
|
||||||
addr.sin_addr.s_addr = ip_addr;
|
addr.sin_addr.s_addr = ip_addr;
|
||||||
|
@ -1273,16 +1335,41 @@ int net_tuntap_set_ipv4(c_uint32_t ip_addr, c_uint8_t bits)
|
||||||
|
|
||||||
(void)memcpy(&ifr.ifr_addr, &addr, sizeof addr);
|
(void)memcpy(&ifr.ifr_addr, &addr, sizeof addr);
|
||||||
if (ioctl(sock, SIOCSIFDSTADDR, &ifr) == -1) {
|
if (ioctl(sock, SIOCSIFDSTADDR, &ifr) == -1) {
|
||||||
d_error("Can't set IP/netmask");
|
d_error("Can't set dst IP/netmask");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
(void)memset(&addr, '\0', sizeof addr);
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_addr.s_addr = ip_addr;
|
||||||
|
addr.sin_len = sizeof addr;
|
||||||
|
(void)memcpy(&ifa.ifra_addr, &addr, sizeof addr);
|
||||||
|
(void)memcpy(&ifa.ifra_broadaddr, &addr, sizeof addr);
|
||||||
|
|
||||||
|
(void)memset(&mask, '\0', sizeof mask);
|
||||||
|
mask.sin_family = AF_INET;
|
||||||
|
mask.sin_addr.s_addr = mask_addr;
|
||||||
|
mask.sin_len = sizeof mask;
|
||||||
|
(void)memcpy(&ifa.ifra_mask, &mask, sizeof ifa.ifra_mask);
|
||||||
|
|
||||||
|
(void)memset(&addr, '\0', sizeof addr);
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_addr.s_addr = ip_addr;
|
||||||
|
addr.sin_len = sizeof addr;
|
||||||
|
(void)memcpy(&ifr.ifr_addr, &addr, sizeof addr);
|
||||||
|
|
||||||
|
if (ioctl(sock, SIOCAIFADDR, &ifa) == -1) {
|
||||||
|
d_error("Can't src IP address(dev:%s err:%s)",
|
||||||
|
link->ifname, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif /* !defined(DARWIN) */
|
||||||
|
|
||||||
close(sock);
|
close(sock);
|
||||||
|
|
||||||
|
#endif /* LINUX == 1 */
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
|
||||||
/* TODO */
|
|
||||||
return 0;
|
|
||||||
#endif /* LINUX != 1 */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1431,7 +1518,7 @@ int net_raw_close(net_link_t *net_link)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int net_tuntap_close(net_link_t *net_link)
|
int net_tun_close(net_link_t *net_link)
|
||||||
{
|
{
|
||||||
d_assert(net_link,return -1, "net_link is NULL\n");
|
d_assert(net_link,return -1, "net_link is NULL\n");
|
||||||
close(net_link->fd);
|
close(net_link->fd);
|
||||||
|
|
|
@ -173,6 +173,8 @@ static int _gtpv1_u_recv_cb(net_sock_t *sock, void *data)
|
||||||
status_t pgw_gtp_open()
|
status_t pgw_gtp_open()
|
||||||
{
|
{
|
||||||
status_t rv;
|
status_t rv;
|
||||||
|
int rc;
|
||||||
|
char buf[INET_ADDRSTRLEN];
|
||||||
|
|
||||||
rv = gtp_listen(&pgw_self()->gtpc_sock, _gtpv2_c_recv_cb,
|
rv = gtp_listen(&pgw_self()->gtpc_sock, _gtpv2_c_recv_cb,
|
||||||
pgw_self()->gtpc_addr, pgw_self()->gtpc_port, NULL);
|
pgw_self()->gtpc_addr, pgw_self()->gtpc_port, NULL);
|
||||||
|
@ -190,52 +192,53 @@ status_t pgw_gtp_open()
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* NOTE : tun device can be created via following command.
|
||||||
|
*
|
||||||
|
* $ sudo ip tuntap add name pgwtun mode tun
|
||||||
|
*
|
||||||
|
* Also, before running pgw, assign the one IP from IP pool of UE
|
||||||
|
* to pgwtun. The IP should not be assigned to UE
|
||||||
|
*
|
||||||
|
* $ sudo ifconfig pgwtun 45.45.0.1/16 up
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Open Tun interface */
|
||||||
|
rc = net_tun_open(&pgw_self()->tun_link, pgw_self()->tun_dev_name, 0);
|
||||||
|
if (rc != 0)
|
||||||
{
|
{
|
||||||
int rc;
|
d_error("Can not open tun(dev : %s)", pgw_self()->tun_dev_name);
|
||||||
int i;
|
return CORE_ERROR;
|
||||||
char buf[INET_ADDRSTRLEN];
|
}
|
||||||
|
|
||||||
/* NOTE : tun device can be created via following command.
|
/*
|
||||||
*
|
* On Linux, it is possible to create a persistent tun/tap
|
||||||
* $ sudo ip tuntap add name pgwtun mode tun
|
* interface which will continue to exist even if nextepc quit,
|
||||||
*
|
* although this is normally not required.
|
||||||
* Also, before running pgw, assign the one IP from IP pool of UE
|
* It can be useful to set up a tun/tap interface owned
|
||||||
* to pgwtun. The IP should not be assigned to UE
|
* by a non-root user, so nextepc can be started without
|
||||||
*
|
* needing any root privileges at all.
|
||||||
* $ sudo ifconfig pgwtun 45.45.0.1/16 up
|
*/
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Open Tun interface */
|
/* Set P-to-P IP address with Netmask
|
||||||
rc = net_tuntap_open(&pgw_self()->tun_link, pgw_self()->tun_dev_name, 0);
|
* Note that Linux will skip this configuration */
|
||||||
if (rc != 0)
|
rc = net_tun_set_ipv4(pgw_self()->tun_link,
|
||||||
{
|
pgw_self()->ip_pool[0].prefix, pgw_self()->ip_pool[0].mask);
|
||||||
d_error("Can not open tun(dev : %s)", pgw_self()->tun_dev_name);
|
if (rc != 0)
|
||||||
return CORE_ERROR;
|
{
|
||||||
}
|
d_error("Can not configure tun(dev : %s for %s/%d)",
|
||||||
|
pgw_self()->tun_dev_name,
|
||||||
for (i = 0; i < pgw_self()->num_of_ip_pool; i++)
|
INET_NTOP(&pgw_self()->ip_pool[0].prefix, buf),
|
||||||
{
|
pgw_self()->ip_pool[0].mask);
|
||||||
rc = net_tuntap_set_ipv4(
|
return CORE_ERROR;
|
||||||
pgw_self()->ip_pool[i].prefix, pgw_self()->ip_pool[i].mask);
|
}
|
||||||
if (rc != 0)
|
|
||||||
{
|
|
||||||
d_error("Can not configure tun(dev : %s for %s/%d)",
|
|
||||||
pgw_self()->tun_dev_name,
|
|
||||||
INET_NTOP(&pgw_self()->ip_pool[i].prefix, buf),
|
|
||||||
pgw_self()->ip_pool[i].mask);
|
|
||||||
return CORE_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = net_register_link(pgw_self()->tun_link, _gtpv1_tun_recv_cb, NULL);
|
|
||||||
if (rc != 0)
|
|
||||||
{
|
|
||||||
d_error("Can not register tun(dev : %s)", pgw_self()->tun_dev_name);
|
|
||||||
net_tuntap_close(pgw_self()->tun_link);
|
|
||||||
return CORE_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
rc = net_register_link(pgw_self()->tun_link, _gtpv1_tun_recv_cb, NULL);
|
||||||
|
if (rc != 0)
|
||||||
|
{
|
||||||
|
d_error("Can not register tun(dev : %s)", pgw_self()->tun_dev_name);
|
||||||
|
net_tun_close(pgw_self()->tun_link);
|
||||||
|
return CORE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
return CORE_OK;
|
return CORE_OK;
|
||||||
|
@ -260,7 +263,7 @@ status_t pgw_gtp_close()
|
||||||
}
|
}
|
||||||
|
|
||||||
net_unregister_link(pgw_self()->tun_link);
|
net_unregister_link(pgw_self()->tun_link);
|
||||||
net_tuntap_close(pgw_self()->tun_link);
|
net_tun_close(pgw_self()->tun_link);
|
||||||
|
|
||||||
return CORE_OK;
|
return CORE_OK;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue