2013年9月9日月曜日

socatでTUN/TAPの中継する

> socat TUN:10.0.0.1/24,tun-type=tap,tun-name=tap1,iff-no-pi,iff-up,iff-promisc TUN:10.0.0.2/24,tun-type=tap,tun-name=tap2,iff-no-pi,iff-up,iff-promisc

IPv4はルーティングの関係でpingもできないが、IPv6のlink localの通信テストは可能。


http://www.dest-unreach.org/socat/doc/socat-tun.html
簡単にトンネルが作れる

疑似シリアル間を中継する

/dev/ptmxで作成した2つの疑似シリアル間を中継する。
スレーブをオープンするまでループバックしてしまうのが問題。


C言語
#define _XOPEN_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

static void dump(char *desc, void *data,int len)
{
	unsigned char *d = (unsigned char*)data;
	int i;
	printf("%s ",desc);
	for(i=0;i<len;i++)
	{
		printf("%02x",d[i]);
	}
	fputs("\n",stdout);
}

int main()
{
	unsigned char buf[64*1024];
	int fd1;
	int fd2;
	int m;
	int r;
	fd_set rdfs;
	
	
	fd1 = open("/dev/ptmx", O_RDWR | O_NOCTTY);
	if(fd1<0)
	{
		perror("open");
		return 1;
	}
	grantpt(fd1);
	unlockpt(fd1);
	printf("%s\n", ptsname(fd1));
	
	fd2 = open("/dev/ptmx", O_RDWR | O_NOCTTY);
	if(fd2<0)
	{
		perror("open");
		return 1;
	}
	grantpt(fd2);
	unlockpt(fd2);
	printf("%s\n", ptsname(fd2));
	
	
	while(1)
	{
		m = (fd1 > fd2) ? fd1 : fd2;
		
		FD_ZERO(&rdfs);
		FD_SET(fd1, &rdfs);
		FD_SET(fd2, &rdfs);
		
		r = select(m+1, &rdfs, NULL, NULL, NULL);
		
		if(r<0)
		{
			perror("select");
			return 1;
		}
		
		if(r)
		{
			if(FD_ISSET(fd1, &rdfs))
			{
				r = read(fd1, buf, sizeof(buf));
				if(r<0)
				{
					perror("read");
					return 1;
				}
				write(fd2, buf, r);
				dump(ptsname(fd1), buf, r);
			}
			
			if(FD_ISSET(fd2, &rdfs))
			{
				r = read(fd2, buf, sizeof(buf));
				if(r<0)
				{
					perror("read");
					return 1;
				}
				write(fd1, buf, r);
				dump(ptsname(fd2), buf, r);
			}
		}
	}
	
	return 0;
}
python
import os
import asyncore
import binascii


class SerialEmu(asyncore.file_dispatcher):

    def __init__(self):
        self.master, self.slave = os.openpty()
        self.slave_name = os.ttyname(self.slave)
        asyncore.file_dispatcher.__init__(self, self.master)

    def handle_read(self):
        d = os.read(self.master,2048)
        os.write(self.opposite.master,d)
        print 'RX %s %s' % (self.slave_name, binascii.b2a_hex(d))

    def writable(self):
        return False


s1 = SerialEmu()
s2 = SerialEmu()

print s1.slave_name
print s2.slave_name

s1.opposite = s2
s2.opposite = s1

asyncore.loop()

TCPとserialを中継する



> socat -T10 TCP-LISTEN:5555,fork,reuseaddr /dev/ttyS0,raw,b115200,echo=0

・TCPポート5555とシリアルを中継
・無通信10秒でTCP切断
・ボーレート115200
・ローカルエコーなし