How to create virtual interface in macOS? - macos

I want to write a simple VPN for my device which can't set up VPN. in Linux I can create a tun interface to deal with this problem. But in macOS I could not find any tun interface in /dev/.
I find some software which implement this function create the utun2 interface, I don't know how to do it.Is there any good example?

I find two good link about this question.
OpenVPN and A node packe
So Here is how to create a uTun interface in macOS:
#include <uv.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/kern_event.h>
#include <sys/socket.h>
#include <strings.h>
#include <sys/ioctl.h>
#include <sys/kern_control.h>
#include <ctype.h>
#include <fcntl.h>
#define UTUN_CONTROL_NAME "com.apple.net.utun_control"
#define UTUN_OPT_IFNAME 2
int open_tun_socket () {
struct sockaddr_ctl addr;
struct ctl_info info;
char ifname[20];
socklen_t ifname_len = sizeof(ifname);
int fd = -1;
int err = 0;
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 = 0;
err = connect(fd, (struct sockaddr *)&addr, sizeof (addr));
if (err != 0) goto on_error;
// TODO: forward ifname (we just expect it to be utun0 for now...)
err = getsockopt(fd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME, ifname, &ifname_len);
if (err != 0) goto on_error;
printf("%s",ifname);
// There is to close the socket,But in this case I don't need it.
//err = fcntl(fd, F_SETFL, O_NONBLOCK);
//if (err != 0) goto on_error;
//fcntl(fd, F_SETFD, FD_CLOEXEC);
//if (err != 0) goto on_error;
on_error:
if (err != 0) {
close(fd);
return err;
}
return fd;
}
int main(){
int result = open_tun_socket();
while( true ){
}
printf("%d",result);
}

Related

Convert *_Ctype_float into float32 in Go

I am new to Go and having difficulty in converting the *_Ctype_float datatype into []float32. Is there something that I am missing? I even thought of converting *_Ctype_float into string but even that was not successful.
I have this C function named predictInstance which returns float*. I am calling this function from Go by
predictionValues := C.predictInstance(
handle,
(*C.float)(unsafe.Pointer(&req.FlatInput[0])),
)
Now when I look at the type of predictionValues it says it is *Ctype_float. Now I want to convert this into []float32
I have a C function which returns a float* array which I wish to convert to []float32. I am calling this
function from Go with a float* array argument.
A working example,
package main
/*
#include <stdlib.h>
#include <float.h>
float *reverse(float *f, int len) {
float *g = calloc(len, sizeof(float));
for (int i = 0; i < len; i++) {
g[i] = f[len-1-i];
}
return g;
}
*/
import "C"
import (
"fmt"
"math"
"unsafe"
)
func main() {
a := []float32{3.14159, 2.718, 1}
r := make([]float32, len(a))
fmt.Println("a:", a, "r:", r)
c := C.reverse((*C.float)(&a[0]), C.int(len(a)))
copy(r, (*[1 << 20]float32)(unsafe.Pointer(c))[:])
C.free(unsafe.Pointer(c))
fmt.Println("a:", a, "r:", r)
}
var okCFloat = func() bool {
if C.sizeof_float != unsafe.Sizeof(float32(0)) {
panic("C float != Go float32")
}
if C.FLT_MAX != math.MaxFloat32 {
panic("C float != Go float32")
}
return true
}()
Output:
a: [3.14159 2.718 1] r: [0 0 0]
a: [3.14159 2.718 1] r: [1 2.718 3.14159]

Runtime error with cgo and certain string slices

I have stripped back a problem I have come across whilst wrapping some C code to work with golang using swig but the problem doesn't rest with swig.
I can pass in a basic string slice but as soon as I construct the slice with anything other than basic strings, I get a panic: runtime error: cgo argument has Go pointer to Go pointer.
go version go1.8.5 linux/amd64
This is the sample code and its output
package main
import (
"fmt"
"reflect"
"unsafe"
)
/*
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct { char *p; int n; } _gostring_;
typedef struct { void* array; int len; int cap; } _goslice_;
void prtText(char * const *txt, int len)
{
int i = 0;
for ( i=0; i<len; i++ ) {
printf("Text %d is: %s\n", i, txt[i]);
}
}
void _wrap_printText(_goslice_ _swig_go_0) {
_gostring_ *p;
char **arg1 = (char **)calloc(_swig_go_0.len, sizeof(char*));
if (arg1) {
for (int i=0; i<_swig_go_0.len; i++) {
p = &(((_gostring_*)_swig_go_0.array)[i]);
arg1[i] = calloc(1,(p->n)+1);
strncpy(arg1[i], p->p, p->n);
}
}
int arg2 = _swig_go_0.len;
prtText((char *const *)arg1,arg2);
}
*/
import "C"
func PrintText(arg1 []string) {
C._wrap_printText(*(*C._goslice_)(unsafe.Pointer(&arg1)))
}
func main() {
s := []string{}
s = append(s, "blah")
s = append(s, "hello")
s = append(s, "again")
ns := []string{}
ns = append(ns, "ns: "+s[0])
ns = append(ns, "ns: "+s[1])
ns = append(ns, "ns: "+s[2])
fmt.Println("type s:", reflect.TypeOf(s))
fmt.Println("type ns:", reflect.TypeOf(ns))
fmt.Println("s:", s)
fmt.Println("ns:", ns)
PrintText(s)
PrintText(ns)
}
go build -i -x -gcflags '-N -l' main.go
./main
type s: []string
type ns: []string
s: [blah hello again]
ns: [ns: blah ns: hello ns: again]
Text 0 is: blah
Text 1 is: hello
Text 2 is: again
panic: runtime error: cgo argument has Go pointer to Go pointer
As you can see, the first string slice works fine but as soon as I do anything other than basic strings, it fails. I've tried making new strings first before appending them to the slice but the problem remains.
What am I doing wrong?
You're basically passing the raw Go pointers.
Instead, you should build C arrays yourself.
As a general rule, seeing unsafe pretty much anywhere should make you suspicious. It is rarely the right way around issues with cgo.
Using the helpers from Passing array of string as parameter from go to C function and using them in your code:
package main
import (
"fmt"
"reflect"
)
/*
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void prtText(char * const *txt, int len)
{
int i = 0;
for ( i=0; i<len; i++ ) {
printf("Text %d is: %s\n", i, txt[i]);
}
}
static char**makeCharArray(int size) {
return calloc(sizeof(char*), size);
}
static void setArrayString(char **a, char *s, int n) {
a[n] = s;
}
static void freeCharArray(char **a, int size) {
int i;
for (i = 0; i < size; i++)
free(a[i]);
free(a);
}
*/
import "C"
func main() {
s := []string{}
s = append(s, "blah")
s = append(s, "hello")
s = append(s, "again")
ns := []string{}
ns = append(ns, "ns: "+s[0])
ns = append(ns, "ns: "+s[1])
ns = append(ns, "ns: "+s[2])
fmt.Println("type s:", reflect.TypeOf(s))
fmt.Println("type ns:", reflect.TypeOf(ns))
fmt.Println("s:", s)
fmt.Println("ns:", ns)
sargs := C.makeCharArray(C.int(len(s)))
defer C.freeCharArray(sargs, C.int(len(s)))
for i, p := range s {
C.setArrayString(sargs, C.CString(p), C.int(i))
}
nsargs := C.makeCharArray(C.int(len(ns)))
defer C.freeCharArray(nsargs, C.int(len(ns)))
for i, p := range ns {
C.setArrayString(nsargs, C.CString(p), C.int(i))
}
C.prtText(sargs, C.int(len(s)))
C.prtText(nsargs, C.int(len(ns)))
}
The output is now as expected:
$ ./main
type s: []string
type ns: []string
s: [blah hello again]
ns: [ns: blah ns: hello ns: again]
Text 0 is: blah
Text 1 is: hello
Text 2 is: again
Text 0 is: ns: blah
Text 1 is: ns: hello
Text 2 is: ns: again

Send SDL frame to another process and display it

I am trying to send a frame to another process in order to display it. I'm using dranger tutorial02.
I was thinking to serialize the SDL_Overlay struct to bytes after the call to sws_scale, send it to the other process, deserialize it and call SDL_DisplayYUVOverlay to display it.
Do you think this is my best choice?
If so, I'm having hard time serializing this struct.. here's the code:
size_t size_of_Overlay(SDL_Overlay *bmp) {
/*
* typedef struct {
*
* Uint32 format;
* int w, h;
* int planes;
* Uint16 *pitches;
* Uint8 **pixels;
* Uint32 hw_overlay:1; <- can I ignore it? cant point to a bit-field..
*
* } SDL_Overlay;
*/
// w,h,planes format pitches pixels
return sizeof(int)*3 + sizeof(Uint32) + sizeof(Uint16)*bmp->w + sizeof(Uint8)*bmp->h*3;
}
void overlay_to_buf(SDL_Overlay* bmp, char* buf) {
if(!bmp || !buf) {
perror("overlay_to_buf");
exit(1);
}
memcpy(buf, &bmp->format, sizeof(Uint32));
buf += sizeof(Uint32);
memcpy(buf, &bmp->w, sizeof(int));
buf += sizeof(int);
memcpy(buf, &bmp->h, sizeof(int));
buf += sizeof(int);
memcpy(buf, &bmp->planes, sizeof(int));
buf += sizeof(int);
memcpy(buf, bmp->pitches, sizeof(Uint16)*bmp->w);
buf += sizeof(Uint16)*bmp->w;
memcpy(buf, bmp->pixels[0], sizeof(Uint8)*bmp->h);
buf += sizeof(Uint8)*bmp->h;
memcpy(buf, bmp->pixels[1], sizeof(Uint8)*bmp->h);
buf += sizeof(Uint8)*bmp->h;
memcpy(buf, bmp->pixels[2], sizeof(Uint8)*bmp->h);
buf += sizeof(Uint8)*bmp->h;
}
void buf_to_overlay(SDL_Overlay *bmp, char* buf) {
if(!bmp || !buf) {
perror("buf_to_overlay");
exit(1);
}
memcpy(&bmp->format, buf, sizeof(Uint32));
buf += sizeof(Uint32);
memcpy(&bmp->w, buf, sizeof(int));
buf += sizeof(int);
memcpy(&bmp->h, buf, sizeof(int));
buf += sizeof(int);
memcpy(&bmp->planes, buf, sizeof(int));
buf += sizeof(int);
bmp->pitches = (Uint16*)malloc(sizeof(Uint16)*bmp->w);
memcpy(bmp->pitches, buf, sizeof(Uint16)*bmp->w);
buf += sizeof(Uint16)*bmp->w;
bmp->pixels[0] = (Uint8*)malloc(sizeof(Uint8)*bmp->h);
memcpy(bmp->pixels[0], buf, sizeof(Uint8)*bmp->h);
buf += sizeof(Uint8)*bmp->h;
bmp->pixels[1] = (Uint8*)malloc(sizeof(Uint8)*bmp->h);
memcpy(bmp->pixels[1], buf, sizeof(Uint8)*bmp->h);
buf += sizeof(Uint8)*bmp->h;
bmp->pixels[2] = (Uint8*)malloc(sizeof(Uint8)*bmp->h);
memcpy(bmp->pixels[2], buf, sizeof(Uint8)*bmp->h);
buf += sizeof(Uint8)*bmp->h;
}
I've succeeded to serialize it and display on the other process..
The way of serialization was wrong, here's the correct code:
size_t size_of_Overlay(SDL_Overlay *bmp) {
/*
* typedef struct {
*
* Uint32 format;
* int w, h;
* int planes;
* Uint16 *pitches;
* Uint8 **pixels;
* Uint32 hw_overlay:1; <- doesn't being accounted
*
* } SDL_Overlay;
*/
return sizeof(int)*3 + sizeof(Uint32) + sizeof(Uint16)*3 + sizeof(Uint8)*bmp->h*bmp->w*3;
}
void overlay_to_buf(SDL_Overlay* bmp, char* buf) {
if(!bmp || !buf) {
perror("overlay_to_buf");
exit(-1);
}
memcpy(buf, &bmp->format, sizeof(Uint32));
buf += sizeof(Uint32);
memcpy(buf, &bmp->w, sizeof(int));
buf += sizeof(int);
memcpy(buf, &bmp->h, sizeof(int));
buf += sizeof(int);
memcpy(buf, &bmp->planes, sizeof(int));
buf += sizeof(int);
memcpy(buf, &bmp->pitches[0], sizeof(Uint16));
buf += sizeof(Uint16);
memcpy(buf, &bmp->pitches[1], sizeof(Uint16));
buf += sizeof(Uint16);
memcpy(buf, &bmp->pitches[2], sizeof(Uint16));
buf += sizeof(Uint16);
memcpy(buf, bmp->pixels[0], sizeof(Uint8)*bmp->h*bmp->w);
buf += sizeof(Uint8)*bmp->h*bmp->w;
memcpy(buf, bmp->pixels[1], sizeof(Uint8)*bmp->h*bmp->w);
buf += sizeof(Uint8)*bmp->h*bmp->w;
memcpy(buf, bmp->pixels[2], sizeof(Uint8)*bmp->h*bmp->w);
}
void buf_to_overlay(SDL_Overlay *bmp, char* buf) {
if(!bmp || !buf) {
perror("to_message");
exit(-1);
}
memcpy(&bmp->format, buf, sizeof(Uint32));
buf += sizeof(Uint32);
memcpy(&bmp->w, buf, sizeof(int));
buf += sizeof(int);
memcpy(&bmp->h, buf, sizeof(int));
buf += sizeof(int);
memcpy(&bmp->planes, buf, sizeof(int));
buf += sizeof(int);
memcpy(&bmp->pitches[0], buf, sizeof(Uint16));
buf += sizeof(Uint16);
memcpy(&bmp->pitches[1], buf, sizeof(Uint16));
buf += sizeof(Uint16);
memcpy(&bmp->pitches[2], buf, sizeof(Uint16));
buf += sizeof(Uint16);
/* pixels are allocated outside the function,
* just one allocation during the whole video since
* the screen size doesn't change.
*/
memcpy(bmp->pixels[0], buf, sizeof(Uint8)*bmp->h*bmp->w);
buf += sizeof(Uint8)*bmp->h*bmp->w;
memcpy(bmp->pixels[1], buf, sizeof(Uint8)*bmp->h*bmp->w);
buf += sizeof(Uint8)*bmp->h*bmp->w;
memcpy(bmp->pixels[2], buf, sizeof(Uint8)*bmp->h*bmp->w);
}

what's difference betwen int ch vs char ch

why for in following function used 't' for int ch"?
ch is int, why use char?
Synopsis:
#include <stdio.h>
char *strrchr(char *string, int c);
Example:
#include <stdio.h>
int main() {
char *s;
char buf [] = "This is a testing";
s = strrchr (buf, 't');
if (s != NULL)
printf ("found a 't' at %s\n", s);
return 0;
}

Returning values through the arguments of go function, which is called from C

Suppose, we've got a Go function, which is doing something with agruments, passed to them, e.g. it could fill the buffer, allocated in the C part and changing it and for example an integer argument, which is a size of read data. It works well with an integer one, but not with a "data part". Just see a code.
package main
/*
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
extern int some(uint8_t *, int *);
static int somewrap() {
uint8_t *i = malloc(16);
int A = 1;
int *x = &A;
some(i, x);
fprintf(stderr, "c.wrapper, i=%s, %p, x=%d, %p\n", i, i, *x, x);
return 0;
}
*/
import "C"
import "fmt"
import (
"unsafe"
)
//export some
func some(i *C.uint8_t, x *C.int) C.int {
fmt.Println("i:", i, &i, *i, "x:", x, &x, *x)
p := []byte("xxx")
i = (*C.uint8_t)(unsafe.Pointer(&p[0]))
*x = C.int(42)
fmt.Println("i:", i, &i, *i, "x:", x, &x, *x)
return C.int(0)
}
func main() {
C.somewrap()
}
As a result, we've got following:
i: 0x4303a40 0xc210000018 0 x: 0x7fff5fbff874 0xc210000020 1
i: 0xc210000038 0xc210000018 120 x: 0x7fff5fbff874 0xc210000020 42
c.wrapper, i=, 0x4303a40, x=42, 0x7fff5fbff874
As you can see, it works well for integer pointer, but not for uint8_t.
You're re-assigning i within some to another address, not change the value at the given address (unless I'm misunderstanding what you're trying to accomplish)
*i = *(*C.uint8_t)(unsafe.Pointer(&p[0]))

Resources