nx_udp_rv.nx source
↩ module page · 66 lines · 2584 B
1// nx_udp_rv.nx -- native-lane UDP socket primitives.
2//
3// Twin of nx_udp.nx, but imports nx_syscalls.nx (RV64-numbered, @ifdef
4// TARGET_X86_64) instead of nx_syscalls_x86_64.nx (raw x86_64 numbers).
5//
6// WHY THIS EXISTS: the native compiler (_offc/nx_compile_x86_native.elf)
7// translates RV64 syscall numbers -> x86_64 at codegen time
8// (nx_x86_64_ctx.nx: 198->41 socket, 200->49 bind, 206->44 sendto,
9// 207->45 recvfrom, 73->7 poll, ...). Code that feeds it raw x86_64
10// numbers (nx_udp.nx -> nx_syscalls_x86_64.nx) hits a collision:
11// x86_64 socket=41 == RV64 unshare=41, so socket() silently became
12// unshare() and every UDP daemon died with -EINVAL before its banner.
13// This is the same syscall-duality class as the documented
14// fork()->openat() leak. Using nx_syscalls.nx (which yields RV64
15// numbers when TARGET_X86_64 is undefined, i.e. the native lane) makes
16// the translation correct. This is the recipe the gated nx_netscope
17// UDP code already uses successfully on the native lane.
18//
19// Use nx_udp_rv.* for daemons built via the native lane; use nx_udp.*
20// for the nxc2.exe --target x86_64 (non-translating) lane.
21
22import "nx_syscalls.nx"
23
24// Open a UDP socket. Returns fd or -errno.
25func nx_udpr_open() -> i64 {
26 return sys_socket(AF_INET, SOCK_DGRAM, 0)
27}
28
29// Fill a 16-byte sockaddr_in for INADDR_ANY:port.
30func nx_udpr_sa_any(out: *u8, port: i64) -> i64 {
31 out[0] = 2; out[1] = 0
32 out[2] = (port >> 8) & 0xff
33 out[3] = port & 0xff
34 var i: i64 = 4
35 while i < 16 { out[i] = 0; i = i + 1 }
36 return 16
37}
38
39// Bind a UDP socket to (INADDR_ANY, port). Returns 0 / -errno.
40func nx_udpr_bind_any(fd: i64, port: i64) -> i64 {
41 let a: *u8 = sys_mmap(16)
42 nx_udpr_sa_any(a, port)
43 return sys_bind(fd, a, 16)
44}
45
46// Fill a 16-byte sockaddr_in for an IPv4 dest a.b.c.d:port.
47func nx_udpr_sa_dest(out: *u8, a: i64, b: i64, c: i64, d: i64, port: i64) -> i64 {
48 out[0] = 2; out[1] = 0
49 out[2] = (port >> 8) & 0xff
50 out[3] = port & 0xff
51 out[4] = a; out[5] = b; out[6] = c; out[7] = d
52 var i: i64 = 8
53 while i < 16 { out[i] = 0; i = i + 1 }
54 return 16
55}
56
57// Send a UDP datagram (flags=0). Returns bytes sent or -errno.
58func nx_udpr_send(fd: i64, buf: *u8, n: i64, addr16: *u8) -> i64 {
59 return sys_sendto(fd, buf, n, 0, addr16, 16)
60}
61
62// Receive a UDP datagram (flags=0). `from` gets the 16-byte source
63// sockaddr_in; `fromlen` is in/out (caller sets 16). Bytes or -errno.
64func nx_udpr_recv(fd: i64, buf: *u8, n: i64, from: *u8, fromlen: *i64) -> i64 {
65 return sys_recvfrom(fd, buf, n, 0, from, fromlen)
66}