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);
|
||||
|
||||
/** TunTap interface */
|
||||
CORE_DECLARE(int) net_tuntap_open(net_link_t **net_link, char *tuntap_dev_name,
|
||||
int is_tap);
|
||||
|
||||
CORE_DECLARE(int) net_tuntap_set_ipv4(c_uint32_t ip_addr, c_uint8_t bits);
|
||||
|
||||
CORE_DECLARE(int) net_tuntap_close(net_link_t *net_link);
|
||||
CORE_DECLARE(int) net_tun_open(net_link_t **net_link, char *name, 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_tun_close(net_link_t *net_link);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -1171,6 +1171,7 @@ int net_raw_open(net_link_t **net_link, int proto)
|
|||
}
|
||||
|
||||
/** Create tuntap socket */
|
||||
#if 0 /* deprecated */
|
||||
int net_tuntap_open(net_link_t **net_link, char *tuntap_dev_name,
|
||||
int is_tap)
|
||||
{
|
||||
|
@ -1224,35 +1225,96 @@ cleanup:
|
|||
return -1;
|
||||
#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
|
||||
/* 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;
|
||||
#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));
|
||||
int sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
|
||||
char *dev = "tun0";
|
||||
|
||||
struct ifaliasreq ifa;
|
||||
struct ifreq ifr;
|
||||
struct sockaddr_in addr;
|
||||
struct sockaddr_in mask;
|
||||
|
||||
(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)strlcpy(ifr.ifr_name, dev, sizeof ifr.ifr_name);
|
||||
(void)strlcpy(ifr.ifr_name, link->ifname, sizeof ifr.ifr_name);
|
||||
|
||||
/* Delete previously assigned address */
|
||||
(void)ioctl(sock, SIOCDIFADDR, &ifr);
|
||||
|
||||
/*
|
||||
* Fill-in the destination address and netmask,
|
||||
* but don't care of the broadcast address
|
||||
*/
|
||||
#if defined(DARWIN)
|
||||
(void)memset(&addr, '\0', sizeof addr);
|
||||
addr.sin_family = AF_INET;
|
||||
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);
|
||||
if (ioctl(sock, SIOCSIFDSTADDR, &ifr) == -1) {
|
||||
d_error("Can't set IP/netmask");
|
||||
d_error("Can't set dst IP/netmask");
|
||||
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);
|
||||
|
||||
#endif /* LINUX == 1 */
|
||||
|
||||
return 0;
|
||||
#else
|
||||
/* TODO */
|
||||
return 0;
|
||||
#endif /* LINUX != 1 */
|
||||
}
|
||||
|
||||
|
||||
|
@ -1431,7 +1518,7 @@ int net_raw_close(net_link_t *net_link)
|
|||
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");
|
||||
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 rv;
|
||||
int rc;
|
||||
char buf[INET_ADDRSTRLEN];
|
||||
|
||||
rv = gtp_listen(&pgw_self()->gtpc_sock, _gtpv2_c_recv_cb,
|
||||
pgw_self()->gtpc_addr, pgw_self()->gtpc_port, NULL);
|
||||
|
@ -190,52 +192,53 @@ status_t pgw_gtp_open()
|
|||
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;
|
||||
int i;
|
||||
char buf[INET_ADDRSTRLEN];
|
||||
d_error("Can not open tun(dev : %s)", pgw_self()->tun_dev_name);
|
||||
return CORE_ERROR;
|
||||
}
|
||||
|
||||
/* 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
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* On Linux, it is possible to create a persistent tun/tap
|
||||
* interface which will continue to exist even if nextepc quit,
|
||||
* although this is normally not required.
|
||||
* It can be useful to set up a tun/tap interface owned
|
||||
* by a non-root user, so nextepc can be started without
|
||||
* needing any root privileges at all.
|
||||
*/
|
||||
|
||||
/* Open Tun interface */
|
||||
rc = net_tuntap_open(&pgw_self()->tun_link, pgw_self()->tun_dev_name, 0);
|
||||
if (rc != 0)
|
||||
{
|
||||
d_error("Can not open tun(dev : %s)", pgw_self()->tun_dev_name);
|
||||
return CORE_ERROR;
|
||||
}
|
||||
|
||||
for (i = 0; i < pgw_self()->num_of_ip_pool; i++)
|
||||
{
|
||||
rc = net_tuntap_set_ipv4(
|
||||
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;
|
||||
}
|
||||
/* Set P-to-P IP address with Netmask
|
||||
* Note that Linux will skip this configuration */
|
||||
rc = net_tun_set_ipv4(pgw_self()->tun_link,
|
||||
pgw_self()->ip_pool[0].prefix, pgw_self()->ip_pool[0].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[0].prefix, buf),
|
||||
pgw_self()->ip_pool[0].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_tun_close(pgw_self()->tun_link);
|
||||
return CORE_ERROR;
|
||||
}
|
||||
|
||||
return CORE_OK;
|
||||
|
@ -260,7 +263,7 @@ status_t pgw_gtp_close()
|
|||
}
|
||||
|
||||
net_unregister_link(pgw_self()->tun_link);
|
||||
net_tuntap_close(pgw_self()->tun_link);
|
||||
net_tun_close(pgw_self()->tun_link);
|
||||
|
||||
return CORE_OK;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue