mirror of
				https://github.com/open5gs/open5gs.git
				synced 2025-11-03 21:43:25 +00:00 
			
		
		
		
	mac: Support Apple M1 chips
See https://open5gs.org/open5gs/docs/platform/05-macosx-apple-silicon/
This commit is contained in:
		@@ -414,11 +414,13 @@ target     prot opt source               destination
 | 
			
		||||
 | 
			
		||||
To enable forwarding and add the NAT rule, enter
 | 
			
		||||
```bash
 | 
			
		||||
### Enable IPv4 Forwarding
 | 
			
		||||
$ sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"
 | 
			
		||||
### Enable IPv4/IPv6 Forwarding
 | 
			
		||||
$ sudo sysctl -w net.ipv4.ip_forward=1
 | 
			
		||||
$ sudo sysctl -w net.ipv6.conf.all.forwarding=1
 | 
			
		||||
 | 
			
		||||
### Add NAT Rule
 | 
			
		||||
$ sudo iptables -t nat -A POSTROUTING -s 10.45.0.0/16 ! -o ogstun -j MASQUERADE
 | 
			
		||||
$ sudo ip6tables -t nat -A POSTROUTING -s cafe::/64 ! -o ogstun -j MASQUERADE
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -444,11 +444,13 @@ target     prot opt source               destination
 | 
			
		||||
Chain POSTROUTING (policy ACCEPT)
 | 
			
		||||
target     prot opt source               destination
 | 
			
		||||
 | 
			
		||||
### Enable IPv4 Forwarding
 | 
			
		||||
$ sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"
 | 
			
		||||
### Enable IPv4/IPv6 Forwarding
 | 
			
		||||
$ sudo sysctl -w net.ipv4.ip_forward=1
 | 
			
		||||
$ sudo sysctl -w net.ipv6.conf.all.forwarding=1
 | 
			
		||||
 | 
			
		||||
### Add NAT Rule
 | 
			
		||||
$ sudo iptables -t nat -A POSTROUTING -s 10.45.0.0/16 ! -o ogstun -j MASQUERADE
 | 
			
		||||
$ sudo ip6tables -t nat -A POSTROUTING -s cafe::/64 ! -o ogstun -j MASQUERADE
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
**Note:** The above assumes you do not have any existing rules in the filter and nat tables. If a program such as docker has already set up rules, you may need to add the Open5GS related rules differently.
 | 
			
		||||
 
 | 
			
		||||
@@ -3,14 +3,23 @@ title: Mac OS X
 | 
			
		||||
head_inline: "<style> .blue { color: blue; } </style>"
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
This guide is based on **macOS Big Sur 11.0.1**.
 | 
			
		||||
This guide is based on macOS Big Sur 11.2 on a Macbook Pro(Intel Chips) computer.
 | 
			
		||||
{: .blue}
 | 
			
		||||
 | 
			
		||||
### Install Xcode Command-Line Tools
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
Homebrew requires the Xcode command-line tools from Apple's Xcode.
 | 
			
		||||
```bash
 | 
			
		||||
$ xcode-select --install
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Installing Homebrew
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
Install brew using the official Homebrew installation instructions.
 | 
			
		||||
```bash
 | 
			
		||||
$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
 | 
			
		||||
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Getting MongoDB
 | 
			
		||||
@@ -32,14 +41,13 @@ $ mongod --config /usr/local/etc/mongod.conf
 | 
			
		||||
{: .notice--info}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### Setting up TUN device (No persistent after rebooting)
 | 
			
		||||
### Setting up network (No persistent after rebooting)
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
Install TUN/TAP driver
 | 
			
		||||
- You can download it from [http://tuntaposx.sourceforge.net/](http://tuntaposx.sourceforge.net/)
 | 
			
		||||
- And then, run tuntap_20150118.pkg to install TUN/TAP driver.
 | 
			
		||||
Note that Open5GS uses built-in "utun" device driver. So, You don't have to install external TUN/TAP driver.
 | 
			
		||||
{: .blue}
 | 
			
		||||
 | 
			
		||||
Configure the TUN device.
 | 
			
		||||
Configure the loopback interface.
 | 
			
		||||
```bash
 | 
			
		||||
$ sudo ifconfig lo0 alias 127.0.0.2 netmask 255.255.255.255
 | 
			
		||||
$ sudo ifconfig lo0 alias 127.0.0.3 netmask 255.255.255.255
 | 
			
		||||
@@ -54,12 +62,21 @@ $ sudo ifconfig lo0 alias 127.0.0.10 netmask 255.255.255.255
 | 
			
		||||
$ sudo ifconfig lo0 alias 127.0.0.11 netmask 255.255.255.255
 | 
			
		||||
$ sudo ifconfig lo0 alias 127.0.0.12 netmask 255.255.255.255
 | 
			
		||||
$ sudo ifconfig lo0 alias 127.0.0.13 netmask 255.255.255.255
 | 
			
		||||
$ sudo ifconfig lo0 alias 127.0.0.14 netmask 255.255.255.255
 | 
			
		||||
$ sudo ifconfig lo0 alias 127.0.0.15 netmask 255.255.255.255
 | 
			
		||||
$ sudo ifconfig lo0 alias 127.0.0.16 netmask 255.255.255.255
 | 
			
		||||
$ sudo ifconfig lo0 alias 127.0.0.17 netmask 255.255.255.255
 | 
			
		||||
$ sudo ifconfig lo0 alias 127.0.0.18 netmask 255.255.255.255
 | 
			
		||||
$ sudo ifconfig lo0 alias 127.0.0.19 netmask 255.255.255.255
 | 
			
		||||
$ sudo ifconfig lo0 alias 127.0.0.20 netmask 255.255.255.255
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Enable IP forwarding & Masquerading
 | 
			
		||||
```bash
 | 
			
		||||
$ sudo sysctl -w net.inet.ip.forwarding=1
 | 
			
		||||
$ sudo sysctl -w net.inet6.ip6.forwarding=1
 | 
			
		||||
$ sudo sh -c "echo 'nat on {en0} from 10.45.0.0/16 to any -> {en0}' > /etc/pf.anchors/org.open5gs"
 | 
			
		||||
$ sudo sh -c "echo 'nat on {en0} from cafe::1/64 to any -> {en0}' > /etc/pf.anchors/org.open5gs"
 | 
			
		||||
$ sudo pfctl -e -f /etc/pf.anchors/org.open5gs
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
@@ -152,4 +169,3 @@ The WebUI runs as an [npm](https://www.npmjs.com/) script.
 | 
			
		||||
```bash
 | 
			
		||||
$ npm run dev
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
@@ -357,9 +357,10 @@ Timeout:               0
 | 
			
		||||
 | 
			
		||||
#### Is it possible to setup IP/NAT table along with Docker?
 | 
			
		||||
 | 
			
		||||
Enable IP Forward.
 | 
			
		||||
Enable IPv4/IPv6 Forward.
 | 
			
		||||
```
 | 
			
		||||
$ sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"
 | 
			
		||||
$ sudo sysctl -w net.ipv4.ip_forward=1
 | 
			
		||||
$ sudo sysctl -w net.ipv6.conf.all.forwarding=1
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The following is the default docker IP/NAT table.
 | 
			
		||||
@@ -435,6 +436,11 @@ And then, apply **newtables** as below.
 | 
			
		||||
$ sudo iptables-restore < newtables
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Docker doesn't have IPv6 NAT rules. In this case, you just add the NAT rule as below.
 | 
			
		||||
```
 | 
			
		||||
$ sudo ip6tables -t nat -A POSTROUTING -s cafe::/64 ! -o ogstun -j MASQUERADE
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The above operation is the same as described in the following manuals.
 | 
			
		||||
```
 | 
			
		||||
### Check IP Tables
 | 
			
		||||
@@ -462,11 +468,13 @@ target     prot opt source               destination
 | 
			
		||||
Chain POSTROUTING (policy ACCEPT)
 | 
			
		||||
target     prot opt source               destination
 | 
			
		||||
 | 
			
		||||
### Enable IPv4 Forwarding
 | 
			
		||||
$ sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"
 | 
			
		||||
### Enable IPv4/IPv6 Forwarding
 | 
			
		||||
$ sudo sysctl -w net.ipv4.ip_forward=1
 | 
			
		||||
$ sudo sysctl -w net.ipv6.conf.all.forwarding=1
 | 
			
		||||
 | 
			
		||||
### Add NAT Rule
 | 
			
		||||
$ sudo iptables -t nat -A POSTROUTING -s 10.45.0.0/16 ! -o ogstun -j MASQUERADE
 | 
			
		||||
$ sudo ip6tables -t nat -A POSTROUTING -s cafe::/64 ! -o ogstun -j MASQUERADE
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### How to use a different DNN/APN for each SMF
 | 
			
		||||
 
 | 
			
		||||
@@ -308,11 +308,13 @@ target     prot opt source               destination
 | 
			
		||||
Chain POSTROUTING (policy ACCEPT)
 | 
			
		||||
target     prot opt source               destination
 | 
			
		||||
 | 
			
		||||
### Enable IPv4 Forwarding
 | 
			
		||||
$ sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"
 | 
			
		||||
### Enable IPv4/IPv6 Forwarding
 | 
			
		||||
$ sudo sysctl -w net.ipv4.ip_forward=1
 | 
			
		||||
$ sudo sysctl -w net.ipv6.conf.all.forwarding=1
 | 
			
		||||
 | 
			
		||||
### Add NAT Rule
 | 
			
		||||
$ sudo iptables -t nat -A POSTROUTING -s 10.45.0.0/16 ! -o ogstun -j MASQUERADE
 | 
			
		||||
$ sudo ip6tables -t nat -A POSTROUTING -s cafe::/64 ! -o ogstun -j MASQUERADE
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
**Note:** For the first time, it is a good condition if you do not have any rules in the IP/NAT tables. If a program such as docker has already set up a rule, you will need to add a rule differently.
 | 
			
		||||
 
 | 
			
		||||
@@ -754,8 +754,8 @@ Below startup script can be used for setting up interfaces:
 | 
			
		||||
```
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"
 | 
			
		||||
sh -c "echo 1 > /proc/sys/net/ipv6/ip_forward"
 | 
			
		||||
sudo sysctl -w net.ipv4.ip_forward=1
 | 
			
		||||
sudo sysctl -w net.ipv6.conf.all.forwarding=1
 | 
			
		||||
 | 
			
		||||
ip tuntap add name ogstun mode tun
 | 
			
		||||
ip addr add 192.168.100.1/24 dev ogstun
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,8 @@ head_inline: "<style> ul { padding-bottom: 1em; } </style>"
 | 
			
		||||
  - [Debian/Ubuntu](platform/01-debian-ubuntu)
 | 
			
		||||
  - [CentOS](platform/02-centos)
 | 
			
		||||
  - [Fedora](platform/03-fedora)
 | 
			
		||||
  - [MacOSX](platform/05-macosx)
 | 
			
		||||
  - [MacOSX(Apple Silicon)](platform/05-macosx-apple-silicon)
 | 
			
		||||
  - [MacOSX(Intel)](platform/06-macosx-intel)
 | 
			
		||||
  
 | 
			
		||||
- Hardware Specific Notes
 | 
			
		||||
  - [Tested e/gNodeBs](hardware/01-genodebs)
 | 
			
		||||
 
 | 
			
		||||
@@ -280,7 +280,6 @@ libcore_sources = files('''
 | 
			
		||||
    ogs-socknode.c
 | 
			
		||||
    ogs-udp.c
 | 
			
		||||
    ogs-tcp.c
 | 
			
		||||
    ogs-tun.c
 | 
			
		||||
    ogs-queue.c
 | 
			
		||||
    ogs-select.c
 | 
			
		||||
    ogs-poll.c
 | 
			
		||||
@@ -304,6 +303,12 @@ if have_func_kqueue
 | 
			
		||||
    libcore_sources += files('ogs-kqueue.c')
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
if host_system == 'darwin'
 | 
			
		||||
    libcore_sources += files('ogs-utun.c')
 | 
			
		||||
else
 | 
			
		||||
    libcore_sources += files('ogs-tun.c')
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
libcore_inc = include_directories('.')
 | 
			
		||||
 | 
			
		||||
libcore = library('ogscore',
 | 
			
		||||
 
 | 
			
		||||
@@ -41,7 +41,10 @@
 | 
			
		||||
ogs_socket_t ogs_tun_open(char *ifname, int len, int is_tap)
 | 
			
		||||
{
 | 
			
		||||
    ogs_socket_t fd = INVALID_SOCKET;
 | 
			
		||||
#if defined(__linux__)
 | 
			
		||||
 | 
			
		||||
#if !defined(__linux__)
 | 
			
		||||
    return fd;
 | 
			
		||||
#else
 | 
			
		||||
    const char *dev = "/dev/net/tun";
 | 
			
		||||
    int rc;
 | 
			
		||||
    struct ifreq ifr;
 | 
			
		||||
@@ -50,334 +53,71 @@ ogs_socket_t ogs_tun_open(char *ifname, int len, int is_tap)
 | 
			
		||||
    ogs_assert(ifname);
 | 
			
		||||
 | 
			
		||||
    fd = open(dev, O_RDWR);
 | 
			
		||||
    if (fd < 0)
 | 
			
		||||
    {
 | 
			
		||||
    if (fd < 0) {
 | 
			
		||||
        ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno,
 | 
			
		||||
                "open() failed : dev[%s]", dev);
 | 
			
		||||
        return INVALID_SOCKET;
 | 
			
		||||
    }
 | 
			
		||||
#else
 | 
			
		||||
    char name[IFNAMSIZ];
 | 
			
		||||
    int tun = 0;
 | 
			
		||||
 | 
			
		||||
    ogs_assert(ifname);
 | 
			
		||||
 | 
			
		||||
#define TUNTAP_ID_MAX 255
 | 
			
		||||
    for (tun = 0; tun < TUNTAP_ID_MAX; tun++)
 | 
			
		||||
    {
 | 
			
		||||
        ogs_snprintf(name, sizeof(name), "/dev/tun%i", tun);
 | 
			
		||||
        if ((fd = open(name, O_RDWR)) > 0)
 | 
			
		||||
        {
 | 
			
		||||
            ogs_snprintf(ifname, len, "tun%i", tun);
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (fd < 0)
 | 
			
		||||
    {
 | 
			
		||||
        ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno,
 | 
			
		||||
                "open() failed");
 | 
			
		||||
        return INVALID_SOCKET;
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(__linux__)
 | 
			
		||||
    memset(&ifr, 0, sizeof(ifr));
 | 
			
		||||
 | 
			
		||||
    ifr.ifr_flags = (is_tap ? (flags | IFF_TAP) : (flags | IFF_TUN));
 | 
			
		||||
    strncpy(ifr.ifr_name, ifname, IFNAMSIZ-1);
 | 
			
		||||
 | 
			
		||||
    rc = ioctl(fd, TUNSETIFF, (void *)&ifr);
 | 
			
		||||
    if (rc < 0)
 | 
			
		||||
    {
 | 
			
		||||
    if (rc < 0) {
 | 
			
		||||
        ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno,
 | 
			
		||||
                "ioctl() failed : dev[%s] flags[0x%x]", dev, flags);
 | 
			
		||||
        goto cleanup;
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    return fd;
 | 
			
		||||
 | 
			
		||||
#if defined(__linux__)
 | 
			
		||||
cleanup:
 | 
			
		||||
    close(fd);
 | 
			
		||||
    return INVALID_SOCKET;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define TUN_ALIGN(size, boundary) \
 | 
			
		||||
        (((size) + ((boundary) - 1)) & ~((boundary) - 1))
 | 
			
		||||
 | 
			
		||||
static int tun_set_ipv4(char *ifname,
 | 
			
		||||
        ogs_ipsubnet_t *ipaddr, ogs_ipsubnet_t *ipsub)
 | 
			
		||||
{
 | 
			
		||||
#if !defined(__linux__) && !defined(WIN32)
 | 
			
		||||
    int fd;
 | 
			
		||||
    
 | 
			
		||||
	struct ifaliasreq ifa;
 | 
			
		||||
	struct ifreq ifr;
 | 
			
		||||
	struct sockaddr_in addr;
 | 
			
		||||
	struct sockaddr_in mask;
 | 
			
		||||
 | 
			
		||||
    char buf[512];
 | 
			
		||||
    int len;
 | 
			
		||||
    struct rt_msghdr *rtm;
 | 
			
		||||
    struct sockaddr_in dst, gw;
 | 
			
		||||
	struct sockaddr_in *paddr;
 | 
			
		||||
 | 
			
		||||
    ogs_assert(ipaddr);
 | 
			
		||||
    ogs_assert(ipsub);
 | 
			
		||||
 | 
			
		||||
    fd = socket(ipaddr->family, SOCK_DGRAM, 0);
 | 
			
		||||
 | 
			
		||||
	(void)memset(&ifa, '\0', sizeof ifa);
 | 
			
		||||
	(void)strlcpy(ifa.ifra_name, ifname, sizeof ifa.ifra_name);
 | 
			
		||||
 | 
			
		||||
	(void)memset(&ifr, '\0', sizeof ifr);
 | 
			
		||||
	(void)strlcpy(ifr.ifr_name, ifname, sizeof ifr.ifr_name);
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
	/* Delete previously assigned address */
 | 
			
		||||
	(void)ioctl(fd, SIOCDIFADDR, &ifr);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	(void)memset(&addr, '\0', sizeof(addr));
 | 
			
		||||
	addr.sin_family = ipaddr->family;
 | 
			
		||||
	addr.sin_addr.s_addr = ipaddr->sub[0];
 | 
			
		||||
	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 = ipaddr->family;
 | 
			
		||||
	mask.sin_addr.s_addr = ipaddr->mask[0];
 | 
			
		||||
	mask.sin_len = sizeof(mask);
 | 
			
		||||
	(void)memcpy(&ifa.ifra_mask, &mask, sizeof(ifa.ifra_mask));
 | 
			
		||||
 | 
			
		||||
	if (ioctl(fd, SIOCAIFADDR, &ifa) == -1) {
 | 
			
		||||
        ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno,
 | 
			
		||||
                "Can't IP address : dev[%s]", ifname);
 | 
			
		||||
		return OGS_ERROR;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    close(fd); /* SOCK_DGRAM */
 | 
			
		||||
 | 
			
		||||
    fd = socket(PF_ROUTE, SOCK_RAW, 0);
 | 
			
		||||
    if (fd < 0)
 | 
			
		||||
    {
 | 
			
		||||
        ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno,
 | 
			
		||||
                "Can't open PF_ROUTE");
 | 
			
		||||
        return OGS_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    (void)memset(&buf, 0, sizeof(buf));
 | 
			
		||||
    rtm = (struct rt_msghdr *)buf;
 | 
			
		||||
    rtm->rtm_type = RTM_ADD;
 | 
			
		||||
    rtm->rtm_version = RTM_VERSION;
 | 
			
		||||
    rtm->rtm_pid = getpid();
 | 
			
		||||
    rtm->rtm_seq = 0;
 | 
			
		||||
    rtm->rtm_flags = RTF_UP | RTF_GATEWAY;
 | 
			
		||||
    rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
 | 
			
		||||
    paddr = (struct sockaddr_in *)(rtm + 1);
 | 
			
		||||
 | 
			
		||||
	(void)memset(&dst, '\0', sizeof(dst));
 | 
			
		||||
	dst.sin_family = ipaddr->family;
 | 
			
		||||
	dst.sin_addr.s_addr = ipsub->sub[0];
 | 
			
		||||
	dst.sin_len = sizeof(dst);
 | 
			
		||||
	(void)memcpy(paddr, &dst, sizeof(dst));
 | 
			
		||||
    paddr = (struct sockaddr_in *)((char *)paddr +
 | 
			
		||||
            TUN_ALIGN(sizeof(*paddr), sizeof(uintptr_t)));
 | 
			
		||||
 | 
			
		||||
	(void)memset(&gw, '\0', sizeof(gw));
 | 
			
		||||
	gw.sin_family = ipaddr->family;
 | 
			
		||||
	gw.sin_addr.s_addr = ipaddr->sub[0];
 | 
			
		||||
	gw.sin_len = sizeof(gw);
 | 
			
		||||
	(void)memcpy(paddr, &gw, sizeof(gw));
 | 
			
		||||
    paddr = (struct sockaddr_in *)((char *)paddr +
 | 
			
		||||
            TUN_ALIGN(sizeof(*paddr), sizeof(uintptr_t)));
 | 
			
		||||
 | 
			
		||||
	(void)memset(&mask, '\0', sizeof(mask));
 | 
			
		||||
	mask.sin_family = ipaddr->family;
 | 
			
		||||
	mask.sin_addr.s_addr = ipsub->mask[0];
 | 
			
		||||
	mask.sin_len = sizeof(mask);
 | 
			
		||||
	(void)memcpy(paddr, &mask, sizeof(mask));
 | 
			
		||||
    paddr = (struct sockaddr_in *)((char *)paddr +
 | 
			
		||||
            TUN_ALIGN(sizeof(*paddr), sizeof(uintptr_t)));
 | 
			
		||||
 | 
			
		||||
    len = (char*)paddr - buf;
 | 
			
		||||
    rtm->rtm_msglen = len;
 | 
			
		||||
    if (write(fd, buf, len) < 0)
 | 
			
		||||
    {
 | 
			
		||||
        ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno,
 | 
			
		||||
                "Can't add routing");
 | 
			
		||||
        return OGS_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    close(fd); /* PF_ROUTE, SOCK_RAW */
 | 
			
		||||
 | 
			
		||||
#endif  /* defined(__linux__) */
 | 
			
		||||
 | 
			
		||||
	return OGS_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int tun_set_ipv6(char *ifname,
 | 
			
		||||
        ogs_ipsubnet_t *ipaddr, ogs_ipsubnet_t *ipsub)
 | 
			
		||||
{
 | 
			
		||||
/* #if !defined(__linux__) && !defined(WIN32) */
 | 
			
		||||
#if 0
 | 
			
		||||
    int fd;
 | 
			
		||||
    
 | 
			
		||||
	struct in6_aliasreq ifa;
 | 
			
		||||
	struct in6_ifreq ifr;
 | 
			
		||||
	struct sockaddr_in6 addr;
 | 
			
		||||
	struct sockaddr_in6 mask;
 | 
			
		||||
 | 
			
		||||
    char buf[512];
 | 
			
		||||
    int len;
 | 
			
		||||
    struct rt_msghdr *rtm;
 | 
			
		||||
#if 0
 | 
			
		||||
    struct sockaddr_in6 dst, gw;
 | 
			
		||||
#else
 | 
			
		||||
    struct sockaddr_in6 dst;
 | 
			
		||||
#endif
 | 
			
		||||
	struct sockaddr_in6 *paddr;
 | 
			
		||||
 | 
			
		||||
    ogs_assert(ipaddr);
 | 
			
		||||
    ogs_assert(ipsub);
 | 
			
		||||
 | 
			
		||||
    fd = socket(ipaddr->family, SOCK_DGRAM, 0);
 | 
			
		||||
 | 
			
		||||
	(void)memset(&ifa, '\0', sizeof ifa);
 | 
			
		||||
	(void)strlcpy(ifa.ifra_name, ifname, sizeof ifa.ifra_name);
 | 
			
		||||
 | 
			
		||||
	(void)memset(&ifr, '\0', sizeof ifr);
 | 
			
		||||
	(void)strlcpy(ifr.ifr_name, ifname, sizeof ifr.ifr_name);
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
	/* Delete previously assigned address */
 | 
			
		||||
	(void)ioctl(fd, SIOCDIFADDR, &ifr);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	(void)memset(&addr, '\0', sizeof(addr));
 | 
			
		||||
	addr.sin6_family = ipaddr->family;
 | 
			
		||||
    memcpy(addr.sin6_addr.s6_addr, ipaddr->sub, sizeof ipaddr->sub);
 | 
			
		||||
	addr.sin6_len = sizeof(addr);
 | 
			
		||||
	(void)memcpy(&ifa.ifra_addr, &addr, sizeof(addr));
 | 
			
		||||
	(void)memcpy(&ifa.ifra_dstaddr, &addr, sizeof(addr));
 | 
			
		||||
 | 
			
		||||
	(void)memset(&mask, '\0', sizeof(mask));
 | 
			
		||||
	mask.sin6_family = ipaddr->family;
 | 
			
		||||
    memcpy(mask.sin6_addr.s6_addr, ipaddr->mask, sizeof ipaddr->mask);
 | 
			
		||||
	mask.sin6_len = sizeof(mask);
 | 
			
		||||
	(void)memcpy(&ifa.ifra_prefixmask, &mask, sizeof(ifa.ifra_prefixmask));
 | 
			
		||||
 | 
			
		||||
    ifa.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
 | 
			
		||||
    ifa.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
 | 
			
		||||
 | 
			
		||||
	if (ioctl(fd, SIOCAIFADDR_IN6, &ifa) == -1) {
 | 
			
		||||
        ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno,
 | 
			
		||||
                "Can't IP address : dev[%s]", ifname);
 | 
			
		||||
		return OGS_ERROR;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    close(fd); /* SOCK_DGRAM */
 | 
			
		||||
 | 
			
		||||
    fd = socket(PF_ROUTE, SOCK_RAW, 0);
 | 
			
		||||
    if (fd < 0)
 | 
			
		||||
    {
 | 
			
		||||
        ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno,
 | 
			
		||||
                "Can't open PF_ROUTE");
 | 
			
		||||
        return OGS_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    (void)memset(&buf, 0, sizeof(buf));
 | 
			
		||||
    rtm = (struct rt_msghdr *)buf;
 | 
			
		||||
    rtm->rtm_type = RTM_DELETE;
 | 
			
		||||
    rtm->rtm_version = RTM_VERSION;
 | 
			
		||||
    rtm->rtm_pid = getpid();
 | 
			
		||||
    rtm->rtm_seq = 0;
 | 
			
		||||
    rtm->rtm_addrs = RTA_DST;
 | 
			
		||||
    paddr = (struct sockaddr_in6 *)(rtm + 1);
 | 
			
		||||
 | 
			
		||||
	(void)memset(&dst, '\0', sizeof(dst));
 | 
			
		||||
	dst.sin6_family = ipaddr->family;
 | 
			
		||||
    memcpy(dst.sin6_addr.s6_addr, ipaddr->sub, sizeof ipsub->sub);
 | 
			
		||||
	dst.sin6_len = sizeof(dst);
 | 
			
		||||
	(void)memcpy(paddr, &dst, sizeof(dst));
 | 
			
		||||
    paddr = (struct sockaddr_in6 *)((char *)paddr +
 | 
			
		||||
            TUN_ALIGN(sizeof(*paddr), sizeof(uintptr_t)));
 | 
			
		||||
 | 
			
		||||
    len = (char*)paddr - buf;
 | 
			
		||||
    rtm->rtm_msglen = len;
 | 
			
		||||
    if (write(fd, buf, len) < 0)
 | 
			
		||||
    {
 | 
			
		||||
        ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno,
 | 
			
		||||
                "Can't add routing");
 | 
			
		||||
        return OGS_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
    (void)memset(&buf, 0, sizeof(buf));
 | 
			
		||||
    rtm = (struct rt_msghdr *)buf;
 | 
			
		||||
    rtm->rtm_type = RTM_ADD;
 | 
			
		||||
    rtm->rtm_version = RTM_VERSION;
 | 
			
		||||
    rtm->rtm_pid = getpid();
 | 
			
		||||
    rtm->rtm_seq = 0;
 | 
			
		||||
    rtm->rtm_flags = RTF_UP | RTF_GATEWAY;
 | 
			
		||||
    rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
 | 
			
		||||
    paddr = (struct sockaddr_in6 *)(rtm + 1);
 | 
			
		||||
 | 
			
		||||
	(void)memset(&dst, '\0', sizeof(dst));
 | 
			
		||||
	dst.sin6_family = ipaddr->family;
 | 
			
		||||
    memcpy(dst.sin6_addr.s6_addr, ipsub->sub, sizeof ipsub->sub);
 | 
			
		||||
	dst.sin6_len = sizeof(dst);
 | 
			
		||||
	(void)memcpy(paddr, &dst, sizeof(dst));
 | 
			
		||||
    paddr = (struct sockaddr_in6 *)((char *)paddr +
 | 
			
		||||
            TUN_ALIGN(sizeof(*paddr), sizeof(uintptr_t)));
 | 
			
		||||
 | 
			
		||||
	(void)memset(&gw, '\0', sizeof(gw));
 | 
			
		||||
	gw.sin6_family = ipaddr->family;
 | 
			
		||||
    memcpy(gw.sin6_addr.s6_addr, ipaddr->sub, sizeof ipaddr->sub);
 | 
			
		||||
	gw.sin6_len = sizeof(gw);
 | 
			
		||||
	(void)memcpy(paddr, &gw, sizeof(gw));
 | 
			
		||||
    paddr = (struct sockaddr_in6 *)((char *)paddr +
 | 
			
		||||
            TUN_ALIGN(sizeof(*paddr), sizeof(uintptr_t)));
 | 
			
		||||
 | 
			
		||||
	(void)memset(&mask, '\0', sizeof(mask));
 | 
			
		||||
	mask.sin6_family = ipaddr->family;
 | 
			
		||||
    memcpy(mask.sin6_addr.s6_addr, ipsub->mask, sizeof ipsub->mask);
 | 
			
		||||
	mask.sin6_len = sizeof(mask);
 | 
			
		||||
	(void)memcpy(paddr, &mask, sizeof(mask));
 | 
			
		||||
    paddr = (struct sockaddr_in6 *)((char *)paddr +
 | 
			
		||||
            TUN_ALIGN(sizeof(*paddr), sizeof(uintptr_t)));
 | 
			
		||||
 | 
			
		||||
    len = (char*)paddr - buf;
 | 
			
		||||
    rtm->rtm_msglen = len;
 | 
			
		||||
    if (write(fd, buf, len) < 0)
 | 
			
		||||
    {
 | 
			
		||||
        ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno,
 | 
			
		||||
                "Can't add routing");
 | 
			
		||||
        return OGS_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    close(fd); /* PF_ROUTE, SOCK_RAW */
 | 
			
		||||
 | 
			
		||||
#endif  /* defined(__linux__) */
 | 
			
		||||
 | 
			
		||||
	return OGS_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ogs_tun_set_ip(char *ifname, ogs_ipsubnet_t *gw, ogs_ipsubnet_t *sub)
 | 
			
		||||
{
 | 
			
		||||
    int rv = OGS_OK;
 | 
			
		||||
 | 
			
		||||
    ogs_assert(gw);
 | 
			
		||||
    ogs_assert(sub);
 | 
			
		||||
 | 
			
		||||
    if (gw->family == AF_INET)
 | 
			
		||||
        rv = tun_set_ipv4(ifname, gw, sub);
 | 
			
		||||
    else if (gw->family == AF_INET6)
 | 
			
		||||
        rv = tun_set_ipv6(ifname, gw, sub);
 | 
			
		||||
 | 
			
		||||
    return rv;
 | 
			
		||||
    return OGS_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ogs_pkbuf_t *ogs_tun_read(ogs_socket_t fd, ogs_pkbuf_pool_t *packet_pool)
 | 
			
		||||
{
 | 
			
		||||
    ogs_pkbuf_t *recvbuf = NULL;
 | 
			
		||||
    int n;
 | 
			
		||||
 | 
			
		||||
    ogs_assert(fd != INVALID_SOCKET);
 | 
			
		||||
    ogs_assert(packet_pool);
 | 
			
		||||
 | 
			
		||||
    recvbuf = ogs_pkbuf_alloc(packet_pool, OGS_MAX_PKT_LEN);
 | 
			
		||||
    ogs_assert(recvbuf);
 | 
			
		||||
    ogs_pkbuf_reserve(recvbuf, OGS_TUN_MAX_HEADROOM);
 | 
			
		||||
    ogs_pkbuf_put(recvbuf, OGS_MAX_PKT_LEN-OGS_TUN_MAX_HEADROOM);
 | 
			
		||||
 | 
			
		||||
    n = ogs_read(fd, recvbuf->data, recvbuf->len);
 | 
			
		||||
    if (n <= 0) {
 | 
			
		||||
        ogs_log_message(OGS_LOG_WARN, ogs_socket_errno, "ogs_read() failed");
 | 
			
		||||
        ogs_pkbuf_free(recvbuf);
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ogs_pkbuf_trim(recvbuf, n);
 | 
			
		||||
 | 
			
		||||
    return recvbuf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ogs_tun_write(ogs_socket_t fd, ogs_pkbuf_t *pkbuf)
 | 
			
		||||
{
 | 
			
		||||
    ogs_assert(fd != INVALID_SOCKET);
 | 
			
		||||
    ogs_assert(pkbuf);
 | 
			
		||||
 | 
			
		||||
    if (ogs_write(fd, pkbuf->data, pkbuf->len) <= 0) {
 | 
			
		||||
        ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, "ogs_write() failed");
 | 
			
		||||
        return OGS_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return OGS_OK;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -26,9 +26,31 @@
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * OGS_TUN_MAX_HEADROOM(16bytes)
 | 
			
		||||
 *
 | 
			
		||||
 * Linux
 | 
			
		||||
 * - ogs_tun_read(16bytes)
 | 
			
		||||
 *   OGS_GTPV1U_5GC_HEADER_LEN(16bytes)
 | 
			
		||||
 * - ogs_tun_write(0bytes)
 | 
			
		||||
 *   No Need for headroom
 | 
			
		||||
 *
 | 
			
		||||
 * Mac OS X
 | 
			
		||||
 * - ogs_tun_read(12bytes)
 | 
			
		||||
 *   OGS_GTPV1U_5GC_HEADER_LEN(16bytes) - Null/Loopback(4bytes)
 | 
			
		||||
 * - ogs_tun_write(4bytes)
 | 
			
		||||
 *   Null/Loopback(4bytes)
 | 
			
		||||
 *
 | 
			
		||||
 * So, we'll just use 12bytes.
 | 
			
		||||
 */
 | 
			
		||||
#define OGS_TUN_MAX_HEADROOM 16
 | 
			
		||||
 | 
			
		||||
ogs_socket_t ogs_tun_open(char *ifname, int len, int is_tap);
 | 
			
		||||
int ogs_tun_set_ip(char *ifname, ogs_ipsubnet_t *gw,  ogs_ipsubnet_t *sub);
 | 
			
		||||
 | 
			
		||||
ogs_pkbuf_t *ogs_tun_read(ogs_socket_t fd, ogs_pkbuf_pool_t *packet_pool);
 | 
			
		||||
int ogs_tun_write(ogs_socket_t fd, ogs_pkbuf_t *pkbuf);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										475
									
								
								lib/core/ogs-utun.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										475
									
								
								lib/core/ogs-utun.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,475 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of Open5GS.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Affero General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "ogs-tun.h"
 | 
			
		||||
 | 
			
		||||
#undef OGS_LOG_DOMAIN
 | 
			
		||||
#define OGS_LOG_DOMAIN __ogs_sock_domain
 | 
			
		||||
 | 
			
		||||
#include <net/if.h>
 | 
			
		||||
#include <net/route.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <sys/ioctl.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
#include <netinet6/in6_var.h>
 | 
			
		||||
#include <netinet6/nd6.h>
 | 
			
		||||
 | 
			
		||||
#include <net/if_utun.h>
 | 
			
		||||
#include <sys/kern_event.h>
 | 
			
		||||
#include <sys/kern_control.h>
 | 
			
		||||
 | 
			
		||||
static int unit = 0;
 | 
			
		||||
 | 
			
		||||
static int utun_open(char *ifname, socklen_t len)
 | 
			
		||||
{
 | 
			
		||||
	struct sockaddr_ctl addr;
 | 
			
		||||
	struct ctl_info info;
 | 
			
		||||
	int fd = -1;
 | 
			
		||||
	int err = 0;
 | 
			
		||||
 | 
			
		||||
    ogs_assert(ifname);
 | 
			
		||||
    ogs_assert(len);
 | 
			
		||||
 | 
			
		||||
	fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL);
 | 
			
		||||
	if (fd < 0) return fd;
 | 
			
		||||
 | 
			
		||||
	bzero(&info, sizeof (info));
 | 
			
		||||
	strncpy(info.ctl_name, UTUN_CONTROL_NAME, MAX_KCTL_NAME);
 | 
			
		||||
 | 
			
		||||
	err = ioctl(fd, CTLIOCGINFO, &info);
 | 
			
		||||
	if (err != 0) goto on_error;
 | 
			
		||||
 | 
			
		||||
	addr.sc_len = sizeof(addr);
 | 
			
		||||
	addr.sc_family = AF_SYSTEM;
 | 
			
		||||
	addr.ss_sysaddr = AF_SYS_CONTROL;
 | 
			
		||||
	addr.sc_id = info.ctl_id;
 | 
			
		||||
	addr.sc_unit = unit + 1;
 | 
			
		||||
 | 
			
		||||
	err = connect(fd, (struct sockaddr *)&addr, sizeof (addr));
 | 
			
		||||
	if (err != 0) goto on_error;
 | 
			
		||||
 | 
			
		||||
	err = getsockopt(fd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME, ifname, &len);
 | 
			
		||||
	if (err != 0) goto on_error;
 | 
			
		||||
 | 
			
		||||
on_error:
 | 
			
		||||
	if (err != 0) {
 | 
			
		||||
		close(fd);
 | 
			
		||||
		return err;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return fd;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ogs_socket_t ogs_tun_open(char *ifname, int len, int is_tap)
 | 
			
		||||
{
 | 
			
		||||
    ogs_socket_t fd = INVALID_SOCKET;
 | 
			
		||||
 | 
			
		||||
    ogs_assert(ifname);
 | 
			
		||||
 | 
			
		||||
#define TUNTAP_ID_MAX 256
 | 
			
		||||
    for (unit = 0; unit < TUNTAP_ID_MAX; unit++) {
 | 
			
		||||
        if ((fd = utun_open(ifname, len)) > 0) {
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (fd < 0) {
 | 
			
		||||
        ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, "open() failed");
 | 
			
		||||
        return INVALID_SOCKET;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return fd;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define TUN_ALIGN(size, boundary) \
 | 
			
		||||
        (((size) + ((boundary) - 1)) & ~((boundary) - 1))
 | 
			
		||||
 | 
			
		||||
static int tun_set_ipv4(char *ifname,
 | 
			
		||||
        ogs_ipsubnet_t *ipaddr, ogs_ipsubnet_t *ipsub)
 | 
			
		||||
{
 | 
			
		||||
    int fd;
 | 
			
		||||
    
 | 
			
		||||
	struct ifaliasreq ifa;
 | 
			
		||||
	struct ifreq ifr;
 | 
			
		||||
	struct sockaddr_in addr;
 | 
			
		||||
	struct sockaddr_in mask;
 | 
			
		||||
 | 
			
		||||
    char buf[512];
 | 
			
		||||
    int len;
 | 
			
		||||
    struct rt_msghdr *rtm;
 | 
			
		||||
    struct sockaddr_in dst, gw;
 | 
			
		||||
	struct sockaddr_in *paddr;
 | 
			
		||||
 | 
			
		||||
    ogs_assert(ipaddr);
 | 
			
		||||
    ogs_assert(ipsub);
 | 
			
		||||
 | 
			
		||||
    fd = socket(ipaddr->family, SOCK_DGRAM, 0);
 | 
			
		||||
 | 
			
		||||
	(void)memset(&ifa, '\0', sizeof ifa);
 | 
			
		||||
	(void)strlcpy(ifa.ifra_name, ifname, sizeof ifa.ifra_name);
 | 
			
		||||
 | 
			
		||||
	(void)memset(&ifr, '\0', sizeof ifr);
 | 
			
		||||
	(void)strlcpy(ifr.ifr_name, ifname, sizeof ifr.ifr_name);
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
	/* Delete previously assigned address */
 | 
			
		||||
	(void)ioctl(fd, SIOCDIFADDR, &ifr);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	(void)memset(&addr, '\0', sizeof(addr));
 | 
			
		||||
	addr.sin_family = ipaddr->family;
 | 
			
		||||
	addr.sin_addr.s_addr = ipaddr->sub[0];
 | 
			
		||||
	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 = ipaddr->family;
 | 
			
		||||
	mask.sin_addr.s_addr = ipaddr->mask[0];
 | 
			
		||||
	mask.sin_len = sizeof(mask);
 | 
			
		||||
	(void)memcpy(&ifa.ifra_mask, &mask, sizeof(ifa.ifra_mask));
 | 
			
		||||
 | 
			
		||||
	if (ioctl(fd, SIOCAIFADDR, &ifa) == -1) {
 | 
			
		||||
        ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno,
 | 
			
		||||
                "Can't IP address : dev[%s]", ifname);
 | 
			
		||||
		return OGS_ERROR;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    close(fd); /* SOCK_DGRAM */
 | 
			
		||||
 | 
			
		||||
    fd = socket(PF_ROUTE, SOCK_RAW, 0);
 | 
			
		||||
    if (fd < 0) {
 | 
			
		||||
        ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno,
 | 
			
		||||
                "Can't open PF_ROUTE");
 | 
			
		||||
        return OGS_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    (void)memset(&buf, 0, sizeof(buf));
 | 
			
		||||
    rtm = (struct rt_msghdr *)buf;
 | 
			
		||||
    rtm->rtm_type = RTM_ADD;
 | 
			
		||||
    rtm->rtm_version = RTM_VERSION;
 | 
			
		||||
    rtm->rtm_pid = getpid();
 | 
			
		||||
    rtm->rtm_seq = 0;
 | 
			
		||||
    rtm->rtm_flags = RTF_UP | RTF_GATEWAY;
 | 
			
		||||
    rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
 | 
			
		||||
    paddr = (struct sockaddr_in *)(rtm + 1);
 | 
			
		||||
 | 
			
		||||
	(void)memset(&dst, '\0', sizeof(dst));
 | 
			
		||||
	dst.sin_family = ipaddr->family;
 | 
			
		||||
	dst.sin_addr.s_addr = ipsub->sub[0];
 | 
			
		||||
	dst.sin_len = sizeof(dst);
 | 
			
		||||
	(void)memcpy(paddr, &dst, sizeof(dst));
 | 
			
		||||
    paddr = (struct sockaddr_in *)((char *)paddr +
 | 
			
		||||
            TUN_ALIGN(sizeof(*paddr), sizeof(uintptr_t)));
 | 
			
		||||
 | 
			
		||||
	(void)memset(&gw, '\0', sizeof(gw));
 | 
			
		||||
	gw.sin_family = ipaddr->family;
 | 
			
		||||
	gw.sin_addr.s_addr = ipaddr->sub[0];
 | 
			
		||||
	gw.sin_len = sizeof(gw);
 | 
			
		||||
	(void)memcpy(paddr, &gw, sizeof(gw));
 | 
			
		||||
    paddr = (struct sockaddr_in *)((char *)paddr +
 | 
			
		||||
            TUN_ALIGN(sizeof(*paddr), sizeof(uintptr_t)));
 | 
			
		||||
 | 
			
		||||
	(void)memset(&mask, '\0', sizeof(mask));
 | 
			
		||||
	mask.sin_family = ipaddr->family;
 | 
			
		||||
	mask.sin_addr.s_addr = ipsub->mask[0];
 | 
			
		||||
	mask.sin_len = sizeof(mask);
 | 
			
		||||
	(void)memcpy(paddr, &mask, sizeof(mask));
 | 
			
		||||
    paddr = (struct sockaddr_in *)((char *)paddr +
 | 
			
		||||
            TUN_ALIGN(sizeof(*paddr), sizeof(uintptr_t)));
 | 
			
		||||
 | 
			
		||||
    len = (char*)paddr - buf;
 | 
			
		||||
    rtm->rtm_msglen = len;
 | 
			
		||||
    if (write(fd, buf, len) < 0) {
 | 
			
		||||
        ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno,
 | 
			
		||||
                "Can't add routing");
 | 
			
		||||
        return OGS_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    close(fd); /* PF_ROUTE, SOCK_RAW */
 | 
			
		||||
 | 
			
		||||
	return OGS_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int contigmask(uint8_t *p, int len)
 | 
			
		||||
{
 | 
			
		||||
	int i, n;
 | 
			
		||||
 | 
			
		||||
	for (i=0; i<len ; i++)
 | 
			
		||||
		if ( (p[i/8] & (1 << (7 - (i%8)))) == 0) /* first bit unset */
 | 
			
		||||
			break;
 | 
			
		||||
	for (n=i+1; n < len; n++)
 | 
			
		||||
		if ( (p[n/8] & (1 << (7 - (n%8)))) != 0)
 | 
			
		||||
			return -1; /* mask not contiguous */
 | 
			
		||||
	return i;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int tun_set_ipv6(char *ifname,
 | 
			
		||||
        ogs_ipsubnet_t *ipaddr, ogs_ipsubnet_t *ipsub)
 | 
			
		||||
{
 | 
			
		||||
#if 1 /* We'll just run ifconfig command in the shell */
 | 
			
		||||
    ogs_proc_t process;
 | 
			
		||||
    int ret = 0, out_return_code = 0;
 | 
			
		||||
 | 
			
		||||
    const char *commandLine[OGS_ARG_MAX];
 | 
			
		||||
    char devname[32];
 | 
			
		||||
    char addr[128];
 | 
			
		||||
 | 
			
		||||
    char buf[OGS_ADDRSTRLEN];
 | 
			
		||||
    int prefixlen;
 | 
			
		||||
 | 
			
		||||
    ogs_assert(ipsub);
 | 
			
		||||
    ogs_assert(ipaddr);
 | 
			
		||||
 | 
			
		||||
#define IPV6_BITLEN    (OGS_IPV6_LEN * 8)
 | 
			
		||||
    prefixlen = contigmask((uint8_t *)ipsub->mask, IPV6_BITLEN);
 | 
			
		||||
 | 
			
		||||
    ogs_snprintf(devname, sizeof devname, "utun%d", unit);
 | 
			
		||||
    ogs_snprintf(addr, sizeof addr, "%s/%d",
 | 
			
		||||
            OGS_INET6_NTOP(ipaddr->sub, buf), prefixlen);
 | 
			
		||||
 | 
			
		||||
    commandLine[0] = "/sbin/ifconfig";
 | 
			
		||||
    commandLine[1] = devname;
 | 
			
		||||
    commandLine[2] = "inet6";
 | 
			
		||||
    commandLine[3] = addr;
 | 
			
		||||
    commandLine[4] = "up";
 | 
			
		||||
    commandLine[5] = NULL;
 | 
			
		||||
 | 
			
		||||
    ret = ogs_proc_create(commandLine, 0, &process);
 | 
			
		||||
    ogs_assert(ret == 0);
 | 
			
		||||
 | 
			
		||||
    ret = ogs_proc_join(&process, &out_return_code);
 | 
			
		||||
    ogs_assert(ret == 0);
 | 
			
		||||
    ogs_assert(out_return_code == 0);
 | 
			
		||||
 | 
			
		||||
    ret = ogs_proc_destroy(&process);
 | 
			
		||||
    ogs_assert(ret == 0);
 | 
			
		||||
 | 
			
		||||
#else /* IPv6 Setting API is not working in UTUN  */
 | 
			
		||||
    int fd;
 | 
			
		||||
    
 | 
			
		||||
	struct in6_aliasreq ifa;
 | 
			
		||||
	struct in6_ifreq ifr;
 | 
			
		||||
	struct sockaddr_in6 addr;
 | 
			
		||||
	struct sockaddr_in6 mask;
 | 
			
		||||
 | 
			
		||||
    char buf[512];
 | 
			
		||||
    int len;
 | 
			
		||||
    struct rt_msghdr *rtm;
 | 
			
		||||
    struct sockaddr_in6 dst, gw;
 | 
			
		||||
	struct sockaddr_in6 *paddr;
 | 
			
		||||
 | 
			
		||||
    ogs_assert(ipaddr);
 | 
			
		||||
    ogs_assert(ipsub);
 | 
			
		||||
 | 
			
		||||
    fd = socket(ipaddr->family, SOCK_DGRAM, 0);
 | 
			
		||||
 | 
			
		||||
	(void)memset(&ifa, '\0', sizeof ifa);
 | 
			
		||||
	(void)strlcpy(ifa.ifra_name, ifname, sizeof ifa.ifra_name);
 | 
			
		||||
 | 
			
		||||
	(void)memset(&ifr, '\0', sizeof ifr);
 | 
			
		||||
	(void)strlcpy(ifr.ifr_name, ifname, sizeof ifr.ifr_name);
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
	/* Delete previously assigned address */
 | 
			
		||||
	(void)ioctl(fd, SIOCDIFADDR, &ifr);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	(void)memset(&addr, '\0', sizeof(addr));
 | 
			
		||||
	addr.sin6_family = ipaddr->family;
 | 
			
		||||
    memcpy(addr.sin6_addr.s6_addr, ipaddr->sub, sizeof ipaddr->sub);
 | 
			
		||||
	addr.sin6_len = sizeof(addr);
 | 
			
		||||
	(void)memcpy(&ifa.ifra_addr, &addr, sizeof(addr));
 | 
			
		||||
	(void)memcpy(&ifa.ifra_dstaddr, &addr, sizeof(addr));
 | 
			
		||||
 | 
			
		||||
	(void)memset(&mask, '\0', sizeof(mask));
 | 
			
		||||
	mask.sin6_family = ipaddr->family;
 | 
			
		||||
    memcpy(mask.sin6_addr.s6_addr, ipaddr->mask, sizeof ipaddr->mask);
 | 
			
		||||
	mask.sin6_len = sizeof(mask);
 | 
			
		||||
	(void)memcpy(&ifa.ifra_prefixmask, &mask, sizeof(ifa.ifra_prefixmask));
 | 
			
		||||
 | 
			
		||||
    ifa.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
 | 
			
		||||
    ifa.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
 | 
			
		||||
 | 
			
		||||
	if (ioctl(fd, SIOCAIFADDR_IN6, &ifa) == -1) {
 | 
			
		||||
        ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno,
 | 
			
		||||
                "Can't IP address : dev[%s]", ifname);
 | 
			
		||||
		return OGS_ERROR;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    close(fd); /* SOCK_DGRAM */
 | 
			
		||||
 | 
			
		||||
    fd = socket(PF_ROUTE, SOCK_RAW, 0);
 | 
			
		||||
    if (fd < 0) {
 | 
			
		||||
        ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno,
 | 
			
		||||
                "Can't open PF_ROUTE");
 | 
			
		||||
        return OGS_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
    (void)memset(&buf, 0, sizeof(buf));
 | 
			
		||||
    rtm = (struct rt_msghdr *)buf;
 | 
			
		||||
    rtm->rtm_type = RTM_DELETE;
 | 
			
		||||
    rtm->rtm_version = RTM_VERSION;
 | 
			
		||||
    rtm->rtm_pid = getpid();
 | 
			
		||||
    rtm->rtm_seq = 0;
 | 
			
		||||
    rtm->rtm_addrs = RTA_DST;
 | 
			
		||||
    paddr = (struct sockaddr_in6 *)(rtm + 1);
 | 
			
		||||
 | 
			
		||||
	(void)memset(&dst, '\0', sizeof(dst));
 | 
			
		||||
	dst.sin6_family = ipaddr->family;
 | 
			
		||||
    memcpy(dst.sin6_addr.s6_addr, ipaddr->sub, sizeof ipsub->sub);
 | 
			
		||||
	dst.sin6_len = sizeof(dst);
 | 
			
		||||
	(void)memcpy(paddr, &dst, sizeof(dst));
 | 
			
		||||
    paddr = (struct sockaddr_in6 *)((char *)paddr +
 | 
			
		||||
            TUN_ALIGN(sizeof(*paddr), sizeof(uintptr_t)));
 | 
			
		||||
 | 
			
		||||
    len = (char*)paddr - buf;
 | 
			
		||||
    rtm->rtm_msglen = len;
 | 
			
		||||
    if (write(fd, buf, len) < 0) {
 | 
			
		||||
        ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno,
 | 
			
		||||
                "Can't add routing");
 | 
			
		||||
        return OGS_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    /* The followings does not work in IPv6 */
 | 
			
		||||
    (void)memset(&buf, 0, sizeof(buf));
 | 
			
		||||
    rtm = (struct rt_msghdr *)buf;
 | 
			
		||||
    rtm->rtm_type = RTM_ADD;
 | 
			
		||||
    rtm->rtm_version = RTM_VERSION;
 | 
			
		||||
    rtm->rtm_pid = getpid();
 | 
			
		||||
    rtm->rtm_seq = 0;
 | 
			
		||||
    rtm->rtm_flags = RTF_UP | RTF_GATEWAY;
 | 
			
		||||
    rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
 | 
			
		||||
    paddr = (struct sockaddr_in6 *)(rtm + 1);
 | 
			
		||||
 | 
			
		||||
	(void)memset(&dst, '\0', sizeof(dst));
 | 
			
		||||
	dst.sin6_family = ipaddr->family;
 | 
			
		||||
    memcpy(dst.sin6_addr.s6_addr, ipsub->sub, sizeof ipsub->sub);
 | 
			
		||||
	dst.sin6_len = sizeof(dst);
 | 
			
		||||
	(void)memcpy(paddr, &dst, sizeof(dst));
 | 
			
		||||
    paddr = (struct sockaddr_in6 *)((char *)paddr +
 | 
			
		||||
            TUN_ALIGN(sizeof(*paddr), sizeof(uintptr_t)));
 | 
			
		||||
 | 
			
		||||
	(void)memset(&gw, '\0', sizeof(gw));
 | 
			
		||||
	gw.sin6_family = ipaddr->family;
 | 
			
		||||
    memcpy(gw.sin6_addr.s6_addr, ipaddr->sub, sizeof ipaddr->sub);
 | 
			
		||||
	gw.sin6_len = sizeof(gw);
 | 
			
		||||
	(void)memcpy(paddr, &gw, sizeof(gw));
 | 
			
		||||
    paddr = (struct sockaddr_in6 *)((char *)paddr +
 | 
			
		||||
            TUN_ALIGN(sizeof(*paddr), sizeof(uintptr_t)));
 | 
			
		||||
 | 
			
		||||
	(void)memset(&mask, '\0', sizeof(mask));
 | 
			
		||||
	mask.sin6_family = ipaddr->family;
 | 
			
		||||
    memcpy(mask.sin6_addr.s6_addr, ipsub->mask, sizeof ipsub->mask);
 | 
			
		||||
	mask.sin6_len = sizeof(mask);
 | 
			
		||||
	(void)memcpy(paddr, &mask, sizeof(mask));
 | 
			
		||||
    paddr = (struct sockaddr_in6 *)((char *)paddr +
 | 
			
		||||
            TUN_ALIGN(sizeof(*paddr), sizeof(uintptr_t)));
 | 
			
		||||
 | 
			
		||||
    len = (char*)paddr - buf;
 | 
			
		||||
    rtm->rtm_msglen = len;
 | 
			
		||||
    if (write(fd, buf, len) < 0) {
 | 
			
		||||
        ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno,
 | 
			
		||||
                "Can't add routing");
 | 
			
		||||
        return OGS_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    close(fd); /* PF_ROUTE, SOCK_RAW */
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	return OGS_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ogs_tun_set_ip(char *ifname, ogs_ipsubnet_t *gw, ogs_ipsubnet_t *sub)
 | 
			
		||||
{
 | 
			
		||||
    int rv = OGS_OK;
 | 
			
		||||
 | 
			
		||||
    ogs_assert(gw);
 | 
			
		||||
    ogs_assert(sub);
 | 
			
		||||
 | 
			
		||||
    if (gw->family == AF_INET)
 | 
			
		||||
        rv = tun_set_ipv4(ifname, gw, sub);
 | 
			
		||||
    else if (gw->family == AF_INET6)
 | 
			
		||||
        rv = tun_set_ipv6(ifname, gw, sub);
 | 
			
		||||
 | 
			
		||||
    return rv;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ogs_pkbuf_t *ogs_tun_read(ogs_socket_t fd, ogs_pkbuf_pool_t *packet_pool)
 | 
			
		||||
{
 | 
			
		||||
    ogs_pkbuf_t *recvbuf = NULL;
 | 
			
		||||
    int n;
 | 
			
		||||
 | 
			
		||||
    ogs_assert(fd != INVALID_SOCKET);
 | 
			
		||||
    ogs_assert(packet_pool);
 | 
			
		||||
 | 
			
		||||
    recvbuf = ogs_pkbuf_alloc(packet_pool, OGS_MAX_PKT_LEN);
 | 
			
		||||
    ogs_assert(recvbuf);
 | 
			
		||||
    ogs_pkbuf_reserve(recvbuf, OGS_TUN_MAX_HEADROOM);
 | 
			
		||||
    ogs_pkbuf_put(recvbuf, OGS_MAX_PKT_LEN-OGS_TUN_MAX_HEADROOM);
 | 
			
		||||
 | 
			
		||||
    n = ogs_read(fd, recvbuf->data, recvbuf->len);
 | 
			
		||||
    if (n <= 0) {
 | 
			
		||||
        ogs_log_message(OGS_LOG_WARN, ogs_socket_errno, "ogs_read() failed");
 | 
			
		||||
        ogs_pkbuf_free(recvbuf);
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ogs_pkbuf_trim(recvbuf, n);
 | 
			
		||||
 | 
			
		||||
    /* Remove Null/Loopback Header (4bytes) */
 | 
			
		||||
    ogs_pkbuf_pull(recvbuf, 4);
 | 
			
		||||
 | 
			
		||||
    return recvbuf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ogs_tun_write(ogs_socket_t fd, ogs_pkbuf_t *pkbuf)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t version;
 | 
			
		||||
    uint32_t family;
 | 
			
		||||
 | 
			
		||||
    ogs_assert(fd != INVALID_SOCKET);
 | 
			
		||||
    ogs_assert(pkbuf);
 | 
			
		||||
 | 
			
		||||
    version = (*((unsigned char *)pkbuf->data) >> 4) & 0xf;
 | 
			
		||||
 | 
			
		||||
    if (version == 4) {
 | 
			
		||||
        family = htobe32(AF_INET);
 | 
			
		||||
    } else if (version == 6) {
 | 
			
		||||
        family = htobe32(AF_INET6);
 | 
			
		||||
    } else {
 | 
			
		||||
        ogs_error("Invalid packet [IP version:%d, Packet Length:%d]",
 | 
			
		||||
                version, pkbuf->len);
 | 
			
		||||
        ogs_log_hexdump(OGS_LOG_ERROR, pkbuf->data, pkbuf->len);
 | 
			
		||||
        return OGS_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ogs_pkbuf_push(pkbuf, sizeof(family));
 | 
			
		||||
    memcpy(pkbuf->data, &family, sizeof(family));
 | 
			
		||||
 | 
			
		||||
    if (ogs_write(fd, pkbuf->data, pkbuf->len) <= 0) {
 | 
			
		||||
        ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, "ogs_write() failed");
 | 
			
		||||
        return OGS_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return OGS_OK;
 | 
			
		||||
}
 | 
			
		||||
@@ -17,6 +17,7 @@ if [ "$SYSTEM" = "Linux" ]; then
 | 
			
		||||
    ip link set ogstun up
 | 
			
		||||
else
 | 
			
		||||
    sysctl -w net.inet.ip.forwarding=1
 | 
			
		||||
    sysctl -w net.inet6.ip6.forwarding=1
 | 
			
		||||
    ifconfig lo0 alias 127.0.0.2 netmask 255.255.255.255
 | 
			
		||||
    ifconfig lo0 alias 127.0.0.3 netmask 255.255.255.255
 | 
			
		||||
    ifconfig lo0 alias 127.0.0.4 netmask 255.255.255.255
 | 
			
		||||
@@ -39,6 +40,7 @@ else
 | 
			
		||||
    if [ "$SYSTEM" = "Darwin" ]; then
 | 
			
		||||
        if ! test -f /etc/pf.anchors/org.open5gs; then
 | 
			
		||||
            sudo sh -c "echo 'nat on {en0} from 10.45.0.0/16 to any -> {en0}' > /etc/pf.anchors/org.open5gs"
 | 
			
		||||
            sudo sh -c "echo 'nat on {en0} from cafe::1/64 to any -> {en0}' > /etc/pf.anchors/org.open5gs"
 | 
			
		||||
        fi
 | 
			
		||||
        pfctl -e -f /etc/pf.anchors/org.open5gs
 | 
			
		||||
    fi
 | 
			
		||||
 
 | 
			
		||||
@@ -52,26 +52,17 @@ static int upf_gtp_send_router_advertisement(
 | 
			
		||||
static void _gtpv1_tun_recv_cb(short when, ogs_socket_t fd, void *data)
 | 
			
		||||
{
 | 
			
		||||
    ogs_pkbuf_t *recvbuf = NULL;
 | 
			
		||||
    int n;
 | 
			
		||||
 | 
			
		||||
    upf_sess_t *sess = NULL;
 | 
			
		||||
    ogs_pfcp_pdr_t *pdr = NULL;
 | 
			
		||||
    ogs_pfcp_user_plane_report_t report;
 | 
			
		||||
 | 
			
		||||
    recvbuf = ogs_pkbuf_alloc(packet_pool, OGS_MAX_PKT_LEN);
 | 
			
		||||
    ogs_assert(recvbuf);
 | 
			
		||||
    ogs_pkbuf_reserve(recvbuf, OGS_GTPV1U_5GC_HEADER_LEN);
 | 
			
		||||
    ogs_pkbuf_put(recvbuf, OGS_MAX_PKT_LEN-OGS_GTPV1U_5GC_HEADER_LEN);
 | 
			
		||||
 | 
			
		||||
    n = ogs_read(fd, recvbuf->data, recvbuf->len);
 | 
			
		||||
    if (n <= 0) {
 | 
			
		||||
        ogs_log_message(OGS_LOG_WARN, ogs_socket_errno, "ogs_read() failed");
 | 
			
		||||
        ogs_pkbuf_free(recvbuf);
 | 
			
		||||
    recvbuf = ogs_tun_read(fd, packet_pool);
 | 
			
		||||
    if (!recvbuf) {
 | 
			
		||||
        ogs_warn("ogs_tun_read() failed");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ogs_pkbuf_trim(recvbuf, n);
 | 
			
		||||
 | 
			
		||||
    /* Find the PDR by packet filter */
 | 
			
		||||
    pdr = upf_pdr_find_by_packet(recvbuf);
 | 
			
		||||
    if (pdr) {
 | 
			
		||||
@@ -119,7 +110,8 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
 | 
			
		||||
 | 
			
		||||
    pkbuf = ogs_pkbuf_alloc(NULL, OGS_MAX_PKT_LEN);
 | 
			
		||||
    ogs_assert(pkbuf);
 | 
			
		||||
    ogs_pkbuf_put(pkbuf, OGS_MAX_PKT_LEN);
 | 
			
		||||
    ogs_pkbuf_reserve(pkbuf, OGS_TUN_MAX_HEADROOM);
 | 
			
		||||
    ogs_pkbuf_put(pkbuf, OGS_MAX_PKT_LEN-OGS_TUN_MAX_HEADROOM);
 | 
			
		||||
 | 
			
		||||
    size = ogs_recvfrom(fd, pkbuf->data, pkbuf->len, 0, &from);
 | 
			
		||||
    if (size <= 0) {
 | 
			
		||||
@@ -288,10 +280,8 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
 | 
			
		||||
 | 
			
		||||
            dev = subnet->dev;
 | 
			
		||||
            ogs_assert(dev);
 | 
			
		||||
            if (ogs_write(dev->fd, pkbuf->data, pkbuf->len) <= 0) {
 | 
			
		||||
                ogs_log_message(OGS_LOG_ERROR,
 | 
			
		||||
                        ogs_socket_errno, "ogs_write() failed");
 | 
			
		||||
            }
 | 
			
		||||
            if (ogs_tun_write(dev->fd, pkbuf) != OGS_OK)
 | 
			
		||||
                ogs_warn("ogs_tun_write() failed");
 | 
			
		||||
        } else {
 | 
			
		||||
            ogs_fatal("Not implemented : FAR-DST_IF[%d]", far->dst_if);
 | 
			
		||||
            ogs_assert_if_reached();
 | 
			
		||||
 
 | 
			
		||||
@@ -141,16 +141,11 @@ ogs_pfcp_pdr_t *upf_pdr_find_by_packet(ogs_pkbuf_t *pkt)
 | 
			
		||||
        addr_len = OGS_IPV6_LEN;
 | 
			
		||||
 | 
			
		||||
        sess = upf_sess_find_by_ipv6(dst_addr);
 | 
			
		||||
    } else
 | 
			
		||||
        ogs_error("Invalid IP version = %d", ip_h->ip_v);
 | 
			
		||||
 | 
			
		||||
    ogs_debug("PROTO:%d SRC:%08x %08x %08x %08x",
 | 
			
		||||
            proto, be32toh(src_addr[0]), be32toh(src_addr[1]),
 | 
			
		||||
            be32toh(src_addr[2]), be32toh(src_addr[3]));
 | 
			
		||||
    ogs_debug("HLEN:%d  DST:%08x %08x %08x %08x",
 | 
			
		||||
            ip_hlen, be32toh(dst_addr[0]), be32toh(dst_addr[1]),
 | 
			
		||||
            be32toh(dst_addr[2]), be32toh(dst_addr[3]));
 | 
			
		||||
 | 
			
		||||
    } else {
 | 
			
		||||
        ogs_error("Invalid packet [IP version:%d, Packet Length:%d]",
 | 
			
		||||
                ip_h->ip_v, pkt->len);
 | 
			
		||||
        ogs_log_hexdump(OGS_LOG_ERROR, pkt->data, pkt->len);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (sess) {
 | 
			
		||||
        ogs_pfcp_pdr_t *fallback_pdr = NULL;
 | 
			
		||||
@@ -158,6 +153,13 @@ ogs_pfcp_pdr_t *upf_pdr_find_by_packet(ogs_pkbuf_t *pkt)
 | 
			
		||||
        ogs_pfcp_far_t *far = NULL;
 | 
			
		||||
        ogs_pfcp_rule_t *rule = NULL;
 | 
			
		||||
 | 
			
		||||
        ogs_debug("PROTO:%d SRC:%08x %08x %08x %08x",
 | 
			
		||||
                proto, be32toh(src_addr[0]), be32toh(src_addr[1]),
 | 
			
		||||
                be32toh(src_addr[2]), be32toh(src_addr[3]));
 | 
			
		||||
        ogs_debug("HLEN:%d  DST:%08x %08x %08x %08x",
 | 
			
		||||
                ip_hlen, be32toh(dst_addr[0]), be32toh(dst_addr[1]),
 | 
			
		||||
                be32toh(dst_addr[2]), be32toh(dst_addr[3]));
 | 
			
		||||
 | 
			
		||||
        if (ip_h && sess->ipv4)
 | 
			
		||||
            ogs_debug("PAA IPv4:%s", OGS_INET_NTOP(&sess->ipv4->addr, buf));
 | 
			
		||||
        if (ip6_h && sess->ipv6)
 | 
			
		||||
 
 | 
			
		||||
@@ -292,7 +292,6 @@ static void test1_func(abts_case *tc, void *data)
 | 
			
		||||
    ABTS_PTR_NOTNULL(tc, recvbuf);
 | 
			
		||||
    ogs_pkbuf_free(recvbuf);
 | 
			
		||||
 | 
			
		||||
#if __linux__
 | 
			
		||||
    /* Send GTP-U ICMP Packet */
 | 
			
		||||
    rv = test_gtpu_send_ping(gtpu, bearer, TEST_PING_IPV6);
 | 
			
		||||
    ABTS_INT_EQUAL(tc, OGS_OK, rv);
 | 
			
		||||
@@ -301,7 +300,6 @@ static void test1_func(abts_case *tc, void *data)
 | 
			
		||||
    recvbuf = test_gtpu_read(gtpu);
 | 
			
		||||
    ABTS_PTR_NOTNULL(tc, recvbuf);
 | 
			
		||||
    ogs_pkbuf_free(recvbuf);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    /* Send Attach Request */
 | 
			
		||||
    memset(&sess->pdn_connectivity_param,
 | 
			
		||||
 
 | 
			
		||||
@@ -86,7 +86,7 @@ static void child_main(void *data)
 | 
			
		||||
    ogs_proc_t *current = NULL;
 | 
			
		||||
    FILE *out = NULL;
 | 
			
		||||
    char buf[OGS_HUGE_LEN];
 | 
			
		||||
    int ret = 0, out_return_code = 0;;
 | 
			
		||||
    int ret = 0, out_return_code = 0;
 | 
			
		||||
 | 
			
		||||
    current = &process[process_num++];
 | 
			
		||||
    ret = ogs_proc_create(commandLine,
 | 
			
		||||
 
 | 
			
		||||
@@ -308,7 +308,6 @@ static void test1_func(abts_case *tc, void *data)
 | 
			
		||||
    ABTS_PTR_NOTNULL(tc, recvbuf);
 | 
			
		||||
    ogs_pkbuf_free(recvbuf);
 | 
			
		||||
 | 
			
		||||
#if __linux__
 | 
			
		||||
    /* Send GTP-U ICMP Packet */
 | 
			
		||||
    rv = test_gtpu_send_ping(gtpu, qos_flow, TEST_PING_IPV6);
 | 
			
		||||
    ABTS_INT_EQUAL(tc, OGS_OK, rv);
 | 
			
		||||
@@ -317,7 +316,6 @@ static void test1_func(abts_case *tc, void *data)
 | 
			
		||||
    recvbuf = test_gtpu_read(gtpu);
 | 
			
		||||
    ABTS_PTR_NOTNULL(tc, recvbuf);
 | 
			
		||||
    ogs_pkbuf_free(recvbuf);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    /* Send Registration request
 | 
			
		||||
     * - Update Registration request type
 | 
			
		||||
@@ -847,7 +845,6 @@ static void test2_func(abts_case *tc, void *data)
 | 
			
		||||
    ABTS_PTR_NOTNULL(tc, recvbuf);
 | 
			
		||||
    ogs_pkbuf_free(recvbuf);
 | 
			
		||||
 | 
			
		||||
#if __linux__
 | 
			
		||||
    /* Send GTP-U ICMP Packet */
 | 
			
		||||
    rv = test_gtpu_send_ping(gtpu, qos_flow, TEST_PING_IPV6);
 | 
			
		||||
    ABTS_INT_EQUAL(tc, OGS_OK, rv);
 | 
			
		||||
@@ -856,7 +853,6 @@ static void test2_func(abts_case *tc, void *data)
 | 
			
		||||
    recvbuf = test_gtpu_read(gtpu);
 | 
			
		||||
    ABTS_PTR_NOTNULL(tc, recvbuf);
 | 
			
		||||
    ogs_pkbuf_free(recvbuf);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    /* Send Registration request
 | 
			
		||||
     * - Update Registration request type
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user