Skip to content

Commit cf15289

Browse files
committed
feat: implement macOS specific socket and tap handling with time retrieval functions
1 parent 8d0dc4a commit cf15289

4 files changed

Lines changed: 265 additions & 2 deletions

File tree

os/macos/os_macos_common.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#ifndef VP_OS_MACOS_COMMON_H
2+
#define VP_OS_MACOS_COMMON_H
3+
4+
#include <stdint.h>
5+
#include <stddef.h>
6+
#include <unistd.h>
7+
#include <fcntl.h>
8+
#include <sys/ioctl.h>
9+
#include <arpa/inet.h>
10+
#include <sys/socket.h>
11+
#include <net/if.h>
12+
#include <string.h>
13+
#include <time.h>
14+
#include <errno.h>
15+
16+
// Returns current time in milliseconds (monotonic)
17+
static inline uint64_t vp_os_macos_get_time_ms(void)
18+
{
19+
struct timespec ts;
20+
clock_gettime(CLOCK_MONOTONIC, &ts);
21+
return (uint64_t)ts.tv_sec * 1000ULL + ts.tv_nsec / 1000000ULL;
22+
}
23+
24+
#endif

os/macos/os_net_macos.c

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
#include "os_macos_common.h"
2+
#include "../../include/os_net.h"
3+
4+
#include <stdlib.h>
5+
6+
struct vp_os_socket {
7+
int fd;
8+
};
9+
10+
int vp_os_udp_open(struct vp_os_socket **sock,
11+
uint32_t bind_ip_be,
12+
uint16_t bind_port_be)
13+
{
14+
struct vp_os_socket *s = calloc(1, sizeof(*s));
15+
if (!s)
16+
return -1;
17+
18+
s->fd = socket(AF_INET, SOCK_DGRAM, 0);
19+
if (s->fd < 0) {
20+
free(s);
21+
return -1;
22+
}
23+
24+
struct sockaddr_in addr;
25+
memset(&addr, 0, sizeof(addr));
26+
addr.sin_family = AF_INET;
27+
addr.sin_addr.s_addr = bind_ip_be;
28+
addr.sin_port = bind_port_be;
29+
30+
if (bind(s->fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
31+
close(s->fd);
32+
free(s);
33+
return -1;
34+
}
35+
36+
int flags = fcntl(s->fd, F_GETFL, 0);
37+
if (flags < 0) {
38+
close(s->fd);
39+
free(s);
40+
return -1;
41+
}
42+
43+
if (fcntl(s->fd, F_SETFL, flags | O_NONBLOCK) < 0) {
44+
close(s->fd);
45+
free(s);
46+
return -1;
47+
}
48+
49+
*sock = s;
50+
return 0;
51+
}
52+
53+
int vp_os_udp_send(struct vp_os_socket *sock,
54+
const struct vp_os_addr *dst,
55+
const uint8_t *buf,
56+
size_t len)
57+
{
58+
struct sockaddr_in addr;
59+
memset(&addr, 0, sizeof(addr));
60+
addr.sin_family = AF_INET;
61+
addr.sin_addr.s_addr = dst->ip_be;
62+
addr.sin_port = dst->port_be;
63+
64+
ssize_t s = sendto(sock->fd, buf, len, 0,
65+
(struct sockaddr *)&addr, sizeof(addr));
66+
return (s == (ssize_t)len) ? 0 : -1;
67+
}
68+
69+
int vp_os_udp_recv(struct vp_os_socket *sock,
70+
struct vp_os_addr *src,
71+
uint8_t *buf,
72+
size_t max_len)
73+
{
74+
struct sockaddr_in addr;
75+
socklen_t alen = sizeof(addr);
76+
77+
ssize_t r = recvfrom(sock->fd, buf, max_len, 0,
78+
(struct sockaddr *)&addr, &alen);
79+
if (r <= 0)
80+
return -1;
81+
82+
src->ip_be = addr.sin_addr.s_addr;
83+
src->port_be = addr.sin_port;
84+
85+
return (int)r;
86+
}
87+
88+
int vp_os_udp_get_fd(struct vp_os_socket *sock)
89+
{
90+
if (!sock)
91+
return -1;
92+
return sock->fd;
93+
}
94+
95+
void vp_os_udp_close(struct vp_os_socket *sock)
96+
{
97+
if (!sock)
98+
return;
99+
close(sock->fd);
100+
free(sock);
101+
}

os/macos/os_tap_macos.c

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
#include "os_macos_common.h"
2+
#include "../../include/os_tap.h"
3+
4+
#include <stdlib.h>
5+
6+
// On macOS we require a /dev/tapX style device as provided
7+
// by a tun/tap kernel extension (e.g. tuntaposx). The daemon
8+
// expects to see raw Ethernet frames, same as on Linux.
9+
10+
struct vp_os_tap {
11+
int fd;
12+
char ifname[IFNAMSIZ];
13+
};
14+
15+
static int vp_open_tap(const char *hint)
16+
{
17+
char path[64];
18+
19+
if (hint && hint[0]) {
20+
// Use the requested interface name directly, e.g. "tap0"
21+
snprintf(path, sizeof(path), "/dev/%s", hint);
22+
} else {
23+
// Default to tap0
24+
snprintf(path, sizeof(path), "/dev/tap0");
25+
}
26+
27+
int fd = open(path, O_RDWR);
28+
if (fd < 0)
29+
return -1;
30+
31+
int flags = fcntl(fd, F_GETFL, 0);
32+
if (flags < 0) {
33+
close(fd);
34+
return -1;
35+
}
36+
37+
if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
38+
close(fd);
39+
return -1;
40+
}
41+
42+
return fd;
43+
}
44+
45+
int vp_os_tap_open(struct vp_os_tap **tap, const char *hint)
46+
{
47+
int fd = vp_open_tap(hint);
48+
if (fd < 0)
49+
return -1;
50+
51+
struct vp_os_tap *t = calloc(1, sizeof(*t));
52+
if (!t) {
53+
close(fd);
54+
return -1;
55+
}
56+
57+
t->fd = fd;
58+
59+
if (hint && hint[0]) {
60+
strncpy(t->ifname, hint, IFNAMSIZ);
61+
t->ifname[IFNAMSIZ - 1] = '\0';
62+
} else {
63+
strncpy(t->ifname, "tap0", IFNAMSIZ);
64+
t->ifname[IFNAMSIZ - 1] = '\0';
65+
}
66+
67+
*tap = t;
68+
return 0;
69+
}
70+
71+
int vp_os_tap_read(struct vp_os_tap *tap, uint8_t *buf, size_t max_len)
72+
{
73+
for (;;) {
74+
ssize_t r = read(tap->fd, buf, max_len);
75+
if (r > 0)
76+
return (int)r;
77+
78+
if (r == 0)
79+
return 0;
80+
81+
if (errno == EINTR)
82+
continue;
83+
84+
if (errno == EAGAIN || errno == EWOULDBLOCK)
85+
return 0;
86+
87+
return -1;
88+
}
89+
}
90+
91+
int vp_os_tap_write(struct vp_os_tap *tap, const uint8_t *buf, size_t len)
92+
{
93+
for (;;) {
94+
ssize_t w = write(tap->fd, buf, len);
95+
if (w > 0) {
96+
if ((size_t)w == len)
97+
return (int)w;
98+
return -1;
99+
}
100+
101+
if (w == 0)
102+
return 0;
103+
104+
if (errno == EINTR)
105+
continue;
106+
107+
if (errno == EAGAIN || errno == EWOULDBLOCK)
108+
return -1;
109+
110+
return -1;
111+
}
112+
}
113+
114+
void vp_os_tap_close(struct vp_os_tap *tap)
115+
{
116+
if (!tap) return;
117+
close(tap->fd);
118+
free(tap);
119+
}

src/vportd.c

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
#include "../include/os_tap.h"
22
#include "../include/os_net.h"
3+
4+
#if defined(__APPLE__)
5+
#include "../os/macos/os_macos_common.h"
6+
#else
37
#include "../os/linux/os_linux_common.h"
8+
#endif
49
#include "../core/protocol.h"
510
#include "../include/vp_types.h"
611
#include "../include/vp_debug.h"
@@ -82,7 +87,11 @@ static int vp_do_handshake(struct vp_os_socket *sock,
8287
uint64_t *last_hello,
8388
int is_reconnect)
8489
{
90+
#if defined(__APPLE__)
91+
uint64_t now = vp_os_macos_get_time_ms();
92+
#else
8593
uint64_t now = vp_os_linux_get_time_ms();
94+
#endif
8695

8796
// Use a per-handshake nonce in seq to bind HELLO_ACKs
8897
// to the corresponding HELLO and prevent replay of old ACKs.
@@ -165,7 +174,12 @@ static int vp_do_handshake(struct vp_os_socket *sock,
165174
memcpy(session_id + 16, buf + hdr.header_len, 16);
166175
vp_crypto_set_session(session_id);
167176

168-
uint64_t t = vp_os_linux_get_time_ms();
177+
uint64_t t =
178+
#if defined(__APPLE__)
179+
vp_os_macos_get_time_ms();
180+
#else
181+
vp_os_linux_get_time_ms();
182+
#endif
169183
*last_recv = t;
170184
*last_activity = t;
171185
*last_keepalive = t;
@@ -242,7 +256,12 @@ int main(int argc, char **argv)
242256

243257
while (g_running) {
244258

245-
uint64_t now = vp_os_linux_get_time_ms();
259+
uint64_t now =
260+
#if defined(__APPLE__)
261+
vp_os_macos_get_time_ms();
262+
#else
263+
vp_os_linux_get_time_ms();
264+
#endif
246265

247266
// -------------------------------
248267
// 1) ADAPTIVE KEEPALIVE LOGIC

0 commit comments

Comments
 (0)