Java code to let Cooja connect to a serial port
This commit is contained in:
parent
64bae5b38d
commit
fb64e64ae2
193
tools/wpcapslip/Connect.java
Normal file
193
tools/wpcapslip/Connect.java
Normal file
|
@ -0,0 +1,193 @@
|
|||
/*
|
||||
* Copyright (c) 2012, Thingsquare, http://www.thingsquare.com/.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
public class Connect {
|
||||
private static Process cmd1Process;
|
||||
private static Process cmd2Process;
|
||||
private static BufferedOutputStream cmd1Out = null;
|
||||
private static BufferedOutputStream cmd2Out = null;
|
||||
|
||||
private static final int BUFSIZE = 512;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (args.length != 2) {
|
||||
System.err.println("Usage: " + Connect.class.getName() + " [cmd1] [cmd2]");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
/* Command 1 */
|
||||
String cmd1 = args[0];
|
||||
System.out.println("> " + cmd1);
|
||||
cmd1Process = Runtime.getRuntime().exec(cmd1, null, new File("."));
|
||||
final DataInputStream cmd1Input = new DataInputStream(
|
||||
cmd1Process.getInputStream());
|
||||
final BufferedReader cmd1Err = new BufferedReader(
|
||||
new InputStreamReader(cmd1Process.getErrorStream()));
|
||||
cmd1Out = new BufferedOutputStream(cmd1Process.getOutputStream());
|
||||
Thread readInput = new Thread(new Runnable() {
|
||||
|
||||
public void run() {
|
||||
int numRead = 0;
|
||||
byte[] buf = new byte[BUFSIZE];
|
||||
try {
|
||||
while (true) {
|
||||
numRead = cmd1Input.read(buf, 0, BUFSIZE);
|
||||
if (numRead > 0 && cmd2Out != null) {
|
||||
/* System.err.println("1>2 " + numRead); */
|
||||
cmd2Out.write(buf, 0, numRead);
|
||||
cmd2Out.flush();
|
||||
}
|
||||
Thread.sleep(1);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
String exitVal = "?";
|
||||
try {
|
||||
if (cmd1Process != null) {
|
||||
exitVal = "" + cmd1Process.exitValue();
|
||||
}
|
||||
} catch (IllegalStateException e) {
|
||||
e.printStackTrace();
|
||||
exitVal = "!";
|
||||
}
|
||||
System.out.println("cmd1 terminated: " + exitVal);
|
||||
exit();
|
||||
}
|
||||
}, "read stdout cmd1");
|
||||
Thread readError = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
String line;
|
||||
try {
|
||||
while ((line = cmd1Err.readLine()) != null) {
|
||||
System.err.println("cmd1 err: " + line);
|
||||
}
|
||||
cmd1Err.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
System.err.println("cmd1 terminated.");
|
||||
exit();
|
||||
}
|
||||
}, "read error cmd1");
|
||||
readInput.start();
|
||||
readError.start();
|
||||
|
||||
/* Command 2 */
|
||||
String cmd2 = args[1];
|
||||
System.err.println("> " + cmd2);
|
||||
cmd2Process = Runtime.getRuntime().exec(cmd2, null, new File("."));
|
||||
final DataInputStream cmd2Input = new DataInputStream(
|
||||
cmd2Process.getInputStream());
|
||||
final BufferedReader cmd2Err = new BufferedReader(
|
||||
new InputStreamReader(cmd2Process.getErrorStream()));
|
||||
cmd2Out = new BufferedOutputStream(cmd2Process.getOutputStream());
|
||||
readInput = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
int numRead = 0;
|
||||
byte[] buf = new byte[BUFSIZE];
|
||||
try {
|
||||
while (true) {
|
||||
numRead = cmd2Input.read(buf, 0, BUFSIZE);
|
||||
if (numRead > 0 && cmd1Out != null) {
|
||||
/* System.err.println("2>1 " + numRead); */
|
||||
cmd1Out.write(buf, 0, numRead);
|
||||
cmd1Out.flush();
|
||||
}
|
||||
Thread.sleep(1);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
String exitVal = "?";
|
||||
try {
|
||||
if (cmd2Process != null) {
|
||||
exitVal = "" + cmd2Process.exitValue();
|
||||
}
|
||||
} catch (IllegalStateException e) {
|
||||
e.printStackTrace();
|
||||
exitVal = "!";
|
||||
}
|
||||
System.out.println("cmd2 terminated: " + exitVal);
|
||||
exit();
|
||||
}
|
||||
}, "read stdout cmd2");
|
||||
readError = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
String line;
|
||||
try {
|
||||
while ((line = cmd2Err.readLine()) != null) {
|
||||
System.err.println("cmd2 err: " + line);
|
||||
}
|
||||
cmd2Err.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
System.err.println("cmd2 terminated.");
|
||||
exit();
|
||||
}
|
||||
}, "read error cmd2");
|
||||
readInput.start();
|
||||
readError.start();
|
||||
|
||||
while (true) {
|
||||
Thread.sleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
private static void exit() {
|
||||
try {
|
||||
Thread.sleep(500);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
try {
|
||||
if (cmd1Process != null) {
|
||||
cmd1Process.destroy();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
try {
|
||||
if (cmd2Process != null) {
|
||||
cmd2Process.destroy();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
System.err.flush();
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
}
|
115
tools/wpcapslip/ConnectSocket.java
Normal file
115
tools/wpcapslip/ConnectSocket.java
Normal file
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright (c) 2013, Thingsquare, http://www.thingsquare.com/.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.net.Socket;
|
||||
|
||||
public class ConnectSocket {
|
||||
private static BufferedOutputStream stdoutOutput = null;
|
||||
private static BufferedOutputStream networkServerOutput = null;
|
||||
|
||||
private static final int BUFSIZE = 512;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (args.length != 2) {
|
||||
System.err.println("Usage: " + ConnectSocket.class.getName() + " [server ip] [server port]");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
/* Stdin */
|
||||
final BufferedInputStream stdinInput = new BufferedInputStream(new DataInputStream(System.in));
|
||||
stdoutOutput = new BufferedOutputStream(System.out);
|
||||
Thread readInput = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
int numRead = 0;
|
||||
byte[] buf = new byte[BUFSIZE];
|
||||
try {
|
||||
while (true) {
|
||||
numRead = stdinInput.read(buf, 0, BUFSIZE);
|
||||
if (numRead > 0 && networkServerOutput != null) {
|
||||
/* System.err.println("1>2 " + numRead); */
|
||||
|
||||
networkServerOutput.write(buf, 0, numRead);
|
||||
networkServerOutput.flush();
|
||||
}
|
||||
Thread.sleep(1);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
exit();
|
||||
}
|
||||
}, "read stdin");
|
||||
readInput.start();
|
||||
|
||||
/* Network server */
|
||||
Socket networkServer = new Socket(args[0], Integer.parseInt(args[1]));
|
||||
final BufferedInputStream networkServerInput = new BufferedInputStream(new DataInputStream(networkServer.getInputStream()));
|
||||
networkServerOutput = new BufferedOutputStream(networkServer.getOutputStream());
|
||||
readInput = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
int numRead = 0;
|
||||
byte[] buf = new byte[BUFSIZE];
|
||||
try {
|
||||
while (true) {
|
||||
numRead = networkServerInput.read(buf, 0, BUFSIZE);
|
||||
if (numRead > 0 && stdoutOutput != null) {
|
||||
/* System.err.println("2>1 " + numRead); */
|
||||
stdoutOutput.write(buf, 0, numRead);
|
||||
stdoutOutput.flush();
|
||||
}
|
||||
Thread.sleep(1);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
exit();
|
||||
}
|
||||
}, "read network server");
|
||||
readInput.start();
|
||||
|
||||
while (true) {
|
||||
Thread.sleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
private static void exit() {
|
||||
try {
|
||||
Thread.sleep(500);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
System.err.flush();
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
|
@ -1,12 +1,21 @@
|
|||
CONTIKI=../..
|
||||
|
||||
CFLAGS=-Wall -Werror -I$(CONTIKI)/core -I.
|
||||
CC=gcc
|
||||
CFLAGS=-Wall -I$(CONTIKI)/core -I.
|
||||
|
||||
all: wpcapslip
|
||||
all: wpcapslip wpcapstdio Connect.class ConnectSocket.class
|
||||
|
||||
%.class: %.java
|
||||
javac $*.java
|
||||
|
||||
vpath %.c $(CONTIKI)/core/net
|
||||
|
||||
wpcapslip: wpcapslip.o wpcap.o tcpdump.o
|
||||
|
||||
wpcapstdio: wpcapstdio.o wpcap.o tcpdump.o
|
||||
|
||||
%: %.o
|
||||
$(CC) $(LDFLAGS) $^ /lib/w32api/libws2_32.a /lib/w32api/libiphlpapi.a -o $@
|
||||
|
||||
clean:
|
||||
rm -f *.class *.exe *.o
|
40
tools/wpcapslip/net/tcpdump.h
Normal file
40
tools/wpcapslip/net/tcpdump.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) 2005, Swedish Institute of Computer Science
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*
|
||||
*/
|
||||
#ifndef __TCPDUMP_H__
|
||||
#define __TCPDUMP_H__
|
||||
|
||||
#include "net/ip/uip.h"
|
||||
|
||||
int tcpdump_format(uint8_t *packet, uint16_t packetlen,
|
||||
char *printbuf, uint16_t printbuflen);
|
||||
|
||||
#endif /* __TCPDUMP_H__ */
|
289
tools/wpcapslip/tcpdump.c
Normal file
289
tools/wpcapslip/tcpdump.c
Normal file
|
@ -0,0 +1,289 @@
|
|||
/*
|
||||
* Copyright (c) 2005, Swedish Institute of Computer Science
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "contiki-net.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
struct ip_hdr {
|
||||
/* IP header. */
|
||||
uint8_t vhl,
|
||||
tos,
|
||||
len[2],
|
||||
ipid[2],
|
||||
ipoffset[2],
|
||||
ttl,
|
||||
proto;
|
||||
uint16_t ipchksum;
|
||||
uint8_t srcipaddr[4],
|
||||
destipaddr[4];
|
||||
};
|
||||
|
||||
#define TCP_FIN 0x01
|
||||
#define TCP_SYN 0x02
|
||||
#define TCP_RST 0x04
|
||||
#define TCP_PSH 0x08
|
||||
#define TCP_ACK 0x10
|
||||
#define TCP_URG 0x20
|
||||
#define TCP_CTL 0x3f
|
||||
|
||||
struct tcpip_hdr {
|
||||
/* IP header. */
|
||||
uint8_t vhl,
|
||||
tos,
|
||||
len[2],
|
||||
ipid[2],
|
||||
ipoffset[2],
|
||||
ttl,
|
||||
proto;
|
||||
uint16_t ipchksum;
|
||||
uint8_t srcipaddr[4],
|
||||
destipaddr[4];
|
||||
/* TCP header. */
|
||||
uint16_t srcport,
|
||||
destport;
|
||||
uint8_t seqno[4],
|
||||
ackno[4],
|
||||
tcpoffset,
|
||||
flags,
|
||||
wnd[2];
|
||||
uint16_t tcpchksum;
|
||||
uint8_t urgp[2];
|
||||
uint8_t optdata[4];
|
||||
};
|
||||
|
||||
#define ICMP_ECHO_REPLY 0
|
||||
#define ICMP_ECHO 8
|
||||
|
||||
struct icmpip_hdr {
|
||||
/* IP header. */
|
||||
uint8_t vhl,
|
||||
tos,
|
||||
len[2],
|
||||
ipid[2],
|
||||
ipoffset[2],
|
||||
ttl,
|
||||
proto;
|
||||
uint16_t ipchksum;
|
||||
uint8_t srcipaddr[4],
|
||||
destipaddr[4];
|
||||
/* The ICMP and IP headers. */
|
||||
/* ICMP (echo) header. */
|
||||
uint8_t type, icode;
|
||||
uint16_t icmpchksum;
|
||||
uint16_t id, seqno;
|
||||
};
|
||||
|
||||
|
||||
/* The UDP and IP headers. */
|
||||
struct udpip_hdr {
|
||||
/* IP header. */
|
||||
uint8_t vhl,
|
||||
tos,
|
||||
len[2],
|
||||
ipid[2],
|
||||
ipoffset[2],
|
||||
ttl,
|
||||
proto;
|
||||
uint16_t ipchksum;
|
||||
uint8_t srcipaddr[4],
|
||||
destipaddr[4];
|
||||
|
||||
/* UDP header. */
|
||||
uint16_t srcport,
|
||||
destport;
|
||||
uint16_t udplen;
|
||||
uint16_t udpchksum;
|
||||
};
|
||||
|
||||
#define ETHBUF ((struct eth_hdr *)&packet[0])
|
||||
#define IPBUF ((struct ip_hdr *)&packet[0])
|
||||
#define UDPBUF ((struct udpip_hdr *)&packet[0])
|
||||
#define ICMPBUF ((struct icmpip_hdr *)&packet[0])
|
||||
#define TCPBUF ((struct tcpip_hdr *)&packet[0])
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
tcpflags(unsigned char flags, char *flagsstr)
|
||||
{
|
||||
if(flags & TCP_FIN) {
|
||||
*flagsstr++ = 'F';
|
||||
}
|
||||
if(flags & TCP_SYN) {
|
||||
*flagsstr++ = 'S';
|
||||
}
|
||||
if(flags & TCP_RST) {
|
||||
*flagsstr++ = 'R';
|
||||
}
|
||||
if(flags & TCP_ACK) {
|
||||
*flagsstr++ = 'A';
|
||||
}
|
||||
if(flags & TCP_URG) {
|
||||
*flagsstr++ = 'U';
|
||||
}
|
||||
|
||||
*flagsstr = 0;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static char * CC_FASTCALL
|
||||
n(uint16_t num, char *ptr)
|
||||
{
|
||||
uint16_t d;
|
||||
uint8_t a, f;
|
||||
|
||||
if(num == 0) {
|
||||
*ptr = '0';
|
||||
return ptr + 1;
|
||||
} else {
|
||||
f = 0;
|
||||
for(d = 10000; d >= 1; d /= 10) {
|
||||
a = (num / d) % 10;
|
||||
if(f == 1 || a > 0) {
|
||||
*ptr = a + '0';
|
||||
++ptr;
|
||||
f = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static char * CC_FASTCALL
|
||||
d(char *ptr)
|
||||
{
|
||||
*ptr = '.';
|
||||
return ptr + 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static char * CC_FASTCALL
|
||||
s(char *str, char *ptr)
|
||||
{
|
||||
strcpy(ptr, str);
|
||||
return ptr + strlen(str);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
tcpdump_format(uint8_t *packet, uint16_t packetlen,
|
||||
char *buf, uint16_t buflen)
|
||||
{
|
||||
char flags[8];
|
||||
if(IPBUF->proto == UIP_PROTO_ICMP) {
|
||||
if(ICMPBUF->type == ICMP_ECHO) {
|
||||
return s(" ping",
|
||||
n(IPBUF->destipaddr[3], d(
|
||||
n(IPBUF->destipaddr[2], d(
|
||||
n(IPBUF->destipaddr[1], d(
|
||||
n(IPBUF->destipaddr[0],
|
||||
s(" ",
|
||||
n(IPBUF->srcipaddr[3], d(
|
||||
n(IPBUF->srcipaddr[2], d(
|
||||
n(IPBUF->srcipaddr[1], d(
|
||||
n(IPBUF->srcipaddr[0],
|
||||
buf)))))))))))))))) - buf;
|
||||
|
||||
/* return sprintf(buf, "%d.%d.%d.%d %d.%d.%d.%d ping",
|
||||
IPBUF->srcipaddr[0], IPBUF->srcipaddr[1],
|
||||
IPBUF->srcipaddr[2], IPBUF->srcipaddr[3],
|
||||
IPBUF->destipaddr[0], IPBUF->destipaddr[1],
|
||||
IPBUF->destipaddr[2], IPBUF->destipaddr[3]);*/
|
||||
} else if(ICMPBUF->type == ICMP_ECHO_REPLY) {
|
||||
return s(" pong",
|
||||
n(IPBUF->destipaddr[3], d(
|
||||
n(IPBUF->destipaddr[2], d(
|
||||
n(IPBUF->destipaddr[1], d(
|
||||
n(IPBUF->destipaddr[0],
|
||||
s(" ",
|
||||
n(IPBUF->srcipaddr[3], d(
|
||||
n(IPBUF->srcipaddr[2], d(
|
||||
n(IPBUF->srcipaddr[1], d(
|
||||
n(IPBUF->srcipaddr[0],
|
||||
buf)))))))))))))))) - buf;
|
||||
/* return sprintf(buf, "%d.%d.%d.%d %d.%d.%d.%d pong",
|
||||
IPBUF->srcipaddr[0], IPBUF->srcipaddr[1],
|
||||
IPBUF->srcipaddr[2], IPBUF->srcipaddr[3],
|
||||
IPBUF->destipaddr[0], IPBUF->destipaddr[1],
|
||||
IPBUF->destipaddr[2], IPBUF->destipaddr[3]);*/
|
||||
}
|
||||
} else if(IPBUF->proto == UIP_PROTO_UDP) {
|
||||
return s(" UDP",
|
||||
n(uip_htons(UDPBUF->destport), d(
|
||||
n(IPBUF->destipaddr[3], d(
|
||||
n(IPBUF->destipaddr[2], d(
|
||||
n(IPBUF->destipaddr[1], d(
|
||||
n(IPBUF->destipaddr[0],
|
||||
s(" ",
|
||||
n(uip_htons(UDPBUF->srcport), d(
|
||||
n(IPBUF->srcipaddr[3], d(
|
||||
n(IPBUF->srcipaddr[2], d(
|
||||
n(IPBUF->srcipaddr[1], d(
|
||||
n(IPBUF->srcipaddr[0],
|
||||
buf)))))))))))))))))))) - buf;
|
||||
/* return sprintf(buf, "%d.%d.%d.%d.%d %d.%d.%d.%d.%d UDP",
|
||||
IPBUF->srcipaddr[0], IPBUF->srcipaddr[1],
|
||||
IPBUF->srcipaddr[2], IPBUF->srcipaddr[3],
|
||||
uip_htons(UDPBUF->srcport),
|
||||
IPBUF->destipaddr[0], IPBUF->destipaddr[1],
|
||||
IPBUF->destipaddr[2], IPBUF->destipaddr[3],
|
||||
uip_htons(UDPBUF->destport));*/
|
||||
} else if(IPBUF->proto == UIP_PROTO_TCP) {
|
||||
tcpflags(TCPBUF->flags, flags);
|
||||
return s(flags,
|
||||
s(" ",
|
||||
n(uip_htons(TCPBUF->destport), d(
|
||||
n(IPBUF->destipaddr[3], d(
|
||||
n(IPBUF->destipaddr[2], d(
|
||||
n(IPBUF->destipaddr[1], d(
|
||||
n(IPBUF->destipaddr[0],
|
||||
s(" ",
|
||||
n(uip_htons(TCPBUF->srcport), d(
|
||||
n(IPBUF->srcipaddr[3], d(
|
||||
n(IPBUF->srcipaddr[2], d(
|
||||
n(IPBUF->srcipaddr[1], d(
|
||||
n(IPBUF->srcipaddr[0],
|
||||
buf))))))))))))))))))))) - buf;
|
||||
/* return sprintf(buf, "%d.%d.%d.%d.%d %d.%d.%d.%d.%d %s",
|
||||
IPBUF->srcipaddr[0], IPBUF->srcipaddr[1],
|
||||
IPBUF->srcipaddr[2], IPBUF->srcipaddr[3],
|
||||
uip_htons(TCPBUF->srcport),
|
||||
IPBUF->destipaddr[0], IPBUF->destipaddr[1],
|
||||
IPBUF->destipaddr[2], IPBUF->destipaddr[3],
|
||||
uip_htons(TCPBUF->destport),
|
||||
flags); */
|
||||
} else {
|
||||
strcpy(buf, "Unrecognized protocol");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
|
@ -58,7 +58,6 @@
|
|||
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <termios.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
@ -69,7 +68,7 @@
|
|||
#define PROGRESS(x)
|
||||
|
||||
|
||||
static void raw_send(void *buf, int len);
|
||||
void raw_send(void *buf, int len);
|
||||
|
||||
struct pcap;
|
||||
|
||||
|
@ -150,7 +149,7 @@ struct arp_entry {
|
|||
struct uip_eth_addr ethaddr;
|
||||
uint8_t time;
|
||||
};
|
||||
static struct uip_eth_addr uip_lladdr = {{0,0,0,0,0,0}};
|
||||
struct uip_eth_addr uip_ethaddr = {{0,0,0,0,0,0}};
|
||||
static const uip_ipaddr_t all_zeroes_addr = { { 0x0, /* rest is 0 */ } };
|
||||
static const struct uip_eth_addr broadcast_ethaddr =
|
||||
{{0xff,0xff,0xff,0xff,0xff,0xff}};
|
||||
|
@ -164,18 +163,20 @@ static int arptime;
|
|||
|
||||
static int logging;
|
||||
|
||||
uip_lladdr_t uip_lladdr;
|
||||
|
||||
static void
|
||||
log_message(char *msg1, char *msg2)
|
||||
{
|
||||
if(logging) {
|
||||
printf("Log: %s %s\n", msg1, msg2);
|
||||
fprintf(stderr, "Log: %s %s\n", msg1, msg2);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
error_exit(char *msg1)
|
||||
{
|
||||
printf("error_exit: %s", msg1);
|
||||
fprintf(stderr, "error_exit: %s", msg1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
@ -263,7 +264,7 @@ set_ethaddr(struct in_addr addr)
|
|||
log_message("set_ethaddr: with address: ", inet_ntoa(adapter_addr));
|
||||
|
||||
if(adapter_addr.s_addr == addr.s_addr) {
|
||||
printf("Using local network interface with address %s\n",
|
||||
fprintf(stderr, "Using local network interface with address %s\n",
|
||||
inet_ntoa(adapter_addr));
|
||||
if(adapters->PhysicalAddressLength != 6) {
|
||||
error_exit("ip addr specified on cmdline does not belong to an ethernet card\n");
|
||||
|
@ -292,12 +293,12 @@ print_packet(unsigned char *buf, int len)
|
|||
int i;
|
||||
|
||||
for(i = 0; i < len; ++i) {
|
||||
printf("0x%02x, ", buf[i]);
|
||||
fprintf(stderr, "0x%02x, ", buf[i]);
|
||||
if(i % 8 == 7) {
|
||||
printf("\n");
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
}
|
||||
printf("\n\n");
|
||||
fprintf(stderr, "\n\n");
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
|
@ -399,7 +400,7 @@ arp_out(struct ethip_hdr *iphdr, int len)
|
|||
int i;
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
#if 0
|
||||
/* Find the destination IP address in the ARP table and construct
|
||||
the Ethernet header. If the destination IP addres isn't on the
|
||||
local network, we use the default router's IP address instead.
|
||||
|
@ -439,8 +440,8 @@ arp_out(struct ethip_hdr *iphdr, int len)
|
|||
|
||||
memset(arphdr->ethhdr.dest.addr, 0xff, 6);
|
||||
memset(arphdr->dhwaddr.addr, 0x00, 6);
|
||||
memcpy(arphdr->ethhdr.src.addr, uip_lladdr.addr, 6);
|
||||
memcpy(arphdr->shwaddr.addr, uip_lladdr.addr, 6);
|
||||
memcpy(arphdr->ethhdr.src.addr, uip_ethaddr.addr, 6);
|
||||
memcpy(arphdr->shwaddr.addr, uip_ethaddr.addr, 6);
|
||||
|
||||
uip_ipaddr_copy(&arphdr->dipaddr, &ipaddr);
|
||||
uip_ipaddr_copy(&arphdr->sipaddr, &netaddr);
|
||||
|
@ -476,14 +477,14 @@ do_arp(void *buf, int len)
|
|||
if(hdr->ethhdr.type == UIP_HTONS(UIP_ETHTYPE_ARP)) {
|
||||
if(hdr->opcode == UIP_HTONS(ARP_REQUEST)) {
|
||||
/* Check if the ARP is for our network */
|
||||
/* printf("ARP for %d.%d.%d.%d we are %d.%d.%d.%d/%d.%d.%d.%d\n",
|
||||
/* fprintf(stderr, "ARP for %d.%d.%d.%d we are %d.%d.%d.%d/%d.%d.%d.%d\n",
|
||||
uip_ipaddr_to_quad(&hdr->dipaddr),
|
||||
uip_ipaddr_to_quad(&netaddr),
|
||||
uip_ipaddr_to_quad(&netmask));*/
|
||||
if(uip_ipaddr_maskcmp(&hdr->dipaddr, &netaddr, &netmask)) {
|
||||
uip_ipaddr_t tmpaddr;
|
||||
|
||||
/* printf("ARP for us.\n");*/
|
||||
/* fprintf(stderr, "ARP for us.\n");*/
|
||||
uip_arp_update(&hdr->sipaddr, &hdr->shwaddr);
|
||||
|
||||
hdr->opcode = UIP_HTONS(ARP_REPLY);
|
||||
|
@ -521,8 +522,8 @@ cleanup(void)
|
|||
char buf[1024];
|
||||
|
||||
snprintf(buf, sizeof(buf), "route delete %d.%d.%d.%d",
|
||||
uip_ipaddr_to_quad(&ifaddr));
|
||||
printf("%s\n", buf);
|
||||
uip_ipaddr_to_quad(&netaddr));
|
||||
fprintf(stderr, "%s\n", buf);
|
||||
system(buf);
|
||||
}
|
||||
|
||||
|
@ -551,7 +552,7 @@ wpcap_start(char *ethcardaddr, char *slipnetaddr, char *slipnetmask, int log)
|
|||
tmpaddr = inet_addr(slipnetmask);
|
||||
memcpy(&netmask.u16[0], &tmpaddr, sizeof(tmpaddr));
|
||||
|
||||
printf("Network address %d.%d.%d.%d/%d.%d.%d.%d\n",
|
||||
fprintf(stderr, "Network address %d.%d.%d.%d/%d.%d.%d.%d\n",
|
||||
uip_ipaddr_to_quad(&netaddr),
|
||||
uip_ipaddr_to_quad(&netmask));
|
||||
|
||||
|
@ -559,7 +560,7 @@ wpcap_start(char *ethcardaddr, char *slipnetaddr, char *slipnetmask, int log)
|
|||
uip_ipaddr_to_quad(&netaddr),
|
||||
uip_ipaddr_to_quad(&netmask),
|
||||
uip_ipaddr_to_quad(&ifaddr));
|
||||
printf("%s\n", buf);
|
||||
fprintf(stderr, "%s\n", buf);
|
||||
system(buf);
|
||||
signal(SIGTERM, remove_route);
|
||||
|
||||
|
@ -593,7 +594,7 @@ wpcap_start(char *ethcardaddr, char *slipnetaddr, char *slipnetmask, int log)
|
|||
if(ret > 0) {
|
||||
/* print_packet(buf, ret);*/
|
||||
if(do_arp(buf, ret)) {
|
||||
printf("IP packet\n");
|
||||
fprintf(stderr, "IP packet\n");
|
||||
}
|
||||
}
|
||||
sleep(1);
|
||||
|
@ -602,17 +603,16 @@ wpcap_start(char *ethcardaddr, char *slipnetaddr, char *slipnetmask, int log)
|
|||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
uint16_t
|
||||
wpcap_poll(char **buf)
|
||||
wpcap_poll(char **buf, int eth)
|
||||
{
|
||||
struct pcap_pkthdr *packet_header;
|
||||
unsigned char *packet;
|
||||
int len;
|
||||
int ret;
|
||||
char *buf2;
|
||||
|
||||
switch(pcap_next_ex(pcap, &packet_header, &packet)) {
|
||||
case -1:
|
||||
error_exit("error on poll\n");
|
||||
case 0:
|
||||
ret = pcap_next_ex(pcap, &packet_header, &packet);
|
||||
if (ret != 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -622,13 +622,20 @@ wpcap_poll(char **buf)
|
|||
|
||||
CopyMemory(*buf, packet, packet_header->caplen);
|
||||
len = packet_header->caplen;
|
||||
/* printf("len %d\n", len);*/
|
||||
|
||||
if(eth) {
|
||||
/* poll requested us to return the raw ethernet packet */
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
buf2 = do_arp(*buf, len);
|
||||
if(buf2 == NULL) {
|
||||
return 0;
|
||||
} else {
|
||||
len = len - (buf2 - *buf);
|
||||
*buf = buf2;
|
||||
/*fprintf(stderr, "wpcap_poll() %d\n", len);*/
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
@ -644,7 +651,7 @@ wpcap_send(void *buf, int len)
|
|||
raw_send(buf2, len);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
void
|
||||
raw_send(void *buf, int len)
|
||||
{
|
||||
/* printf("sending len %d\n", len);*/
|
||||
|
|
|
@ -47,8 +47,6 @@
|
|||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/select.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
@ -75,6 +73,18 @@ static int should_print = 0;
|
|||
|
||||
#define IP_HLEN 20
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
uint16_t
|
||||
uip_htons(uint16_t val)
|
||||
{
|
||||
return UIP_HTONS(val);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
uint32_t
|
||||
uip_htonl(uint32_t val)
|
||||
{
|
||||
return UIP_HTONL(val);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
print_packet(uint8_t *packet, int len)
|
||||
|
@ -289,8 +299,9 @@ serial_to_wpcap(FILE *inslip)
|
|||
*/
|
||||
#define DEBUG_LINE_MARKER '\r'
|
||||
int ecode;
|
||||
|
||||
ecode = check_ip(&uip.iphdr, inbufptr);
|
||||
if(ecode < 0 && inbufptr == 8 && strncmp(uip.inbuf, "=IPA", 4) == 0) {
|
||||
if(ecode < 0 && inbufptr == 8 && strncmp((const char*)uip.inbuf, "=IPA", 4) == 0) {
|
||||
static struct in_addr ipa;
|
||||
|
||||
inbufptr = 0;
|
||||
|
@ -902,7 +913,7 @@ main(int argc, char **argv)
|
|||
if(iphdr->ip_id != last_id) {
|
||||
last_id = iphdr->ip_id;
|
||||
/* printf("------ wpcap_poll ret %d\n", ret);*/
|
||||
print_packet(pbuf, ret);
|
||||
print_packet((uint8_t*)pbuf, ret);
|
||||
write_to_serial(slipfd, pbuf, ret);
|
||||
slip_flushbuf(slipfd);
|
||||
sigalarm_reset();
|
||||
|
|
597
tools/wpcapslip/wpcapstdio.c
Normal file
597
tools/wpcapslip/wpcapstdio.c
Normal file
|
@ -0,0 +1,597 @@
|
|||
/*
|
||||
* Copyright (c) 2012, Thingsquare, www.thingsquare.com.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*
|
||||
* Author: Fredrik Osterlind <fredrik@thingsquare.com>
|
||||
* Based on wpcapslip.c by : Oliver Schmidt <ol.sc@web.de>
|
||||
*/
|
||||
|
||||
/* This is a stripped-down version of wpcapslip: Instead of reading from and writing
|
||||
* to a serial port, this program just reads and writes to stdin/stdout. To
|
||||
* achieve the same functionality as wpcapslip, this program can hence be connected
|
||||
* to serialdump. But, in contrast to wpcapslip, this program can easily be connected
|
||||
* to networked or simulated serial ports. -- Fredrik, 2012 */
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef __CYGWIN__
|
||||
#include <alloca.h>
|
||||
#else /* __CYGWIN__ */
|
||||
#include <malloc.h>
|
||||
#endif /* __CYGWIN__ */
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/select.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <termios.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <err.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#define PROGRESS(x)
|
||||
|
||||
void wpcap_start(char *ethifaddr, char *netaddr, char *netmask, int logging);
|
||||
|
||||
void wpcap_send(void *buf, int len);
|
||||
void raw_send(void *buf, int len);
|
||||
|
||||
uint16_t wpcap_poll(char **buf, int eth);
|
||||
|
||||
#include "net/tcpdump.h"
|
||||
static int should_print = 0;
|
||||
|
||||
static int send_eth = 0; /* Sends ethernet frames or IP packets */
|
||||
|
||||
#define IP_HLEN 20
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
uint16_t
|
||||
uip_htons(uint16_t val)
|
||||
{
|
||||
return UIP_HTONS(val);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
uint32_t
|
||||
uip_htonl(uint32_t val)
|
||||
{
|
||||
return UIP_HTONL(val);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
print_packet(char* prefix, uint8_t *packet, int len)
|
||||
{
|
||||
char buf[2000];
|
||||
if(should_print) {
|
||||
tcpdump_format(packet, len, buf, sizeof(buf));
|
||||
fprintf(stderr, "%s: %s\n", prefix, buf);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void cleanup(void);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
sigcleanup(int signo)
|
||||
{
|
||||
fprintf(stderr, "signal %d\n", signo);
|
||||
exit(0); /* exit(0) will call cleanup() */
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#define SLIP_END 0300
|
||||
#define SLIP_ESC 0333
|
||||
#define SLIP_ESC_END 0334
|
||||
#define SLIP_ESC_ESC 0335
|
||||
|
||||
struct ip {
|
||||
u_int8_t ip_vhl; /* version and header length */
|
||||
#define IP_V4 0x40
|
||||
#define IP_V 0xf0
|
||||
#define IP_HL 0x0f
|
||||
u_int8_t ip_tos; /* type of service */
|
||||
u_int16_t ip_len; /* total length */
|
||||
u_int16_t ip_id; /* identification */
|
||||
u_int16_t ip_off; /* fragment offset field */
|
||||
#define IP_RF 0x8000 /* reserved fragment flag */
|
||||
#define IP_DF 0x4000 /* dont fragment flag */
|
||||
#define IP_MF 0x2000 /* more fragments flag */
|
||||
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
|
||||
u_int8_t ip_ttl; /* time to live */
|
||||
u_int8_t ip_p; /* protocol */
|
||||
u_int16_t ip_sum; /* checksum */
|
||||
u_int32_t ip_src, ip_dst; /* source and dest address */
|
||||
u_int16_t uh_sport; /* source port */
|
||||
u_int16_t uh_dport; /* destination port */
|
||||
u_int16_t uh_ulen; /* udp length */
|
||||
u_int16_t uh_sum; /* udp checksum */
|
||||
};
|
||||
|
||||
static int ip_id, last_id;
|
||||
|
||||
int
|
||||
ssystem(const char *fmt, ...) __attribute__((__format__ (__printf__, 1, 2)));
|
||||
|
||||
int
|
||||
ssystem(const char *fmt, ...)
|
||||
{
|
||||
char cmd[128];
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(cmd, sizeof(cmd), fmt, ap);
|
||||
va_end(ap);
|
||||
fprintf(stderr, "%s\n", cmd);
|
||||
fflush(stderr);
|
||||
return system(cmd);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
is_sensible_string(const unsigned char *s, int len)
|
||||
{
|
||||
int i;
|
||||
for(i = 1; i < len; i++) {
|
||||
if(s[i] == 0 || s[i] == '\r' || s[i] == '\n' || s[i] == '\t') {
|
||||
continue;
|
||||
} else if(s[i] < ' ' || '~' < s[i]) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
u_int16_t
|
||||
ip4sum(u_int16_t sum, const void *_p, u_int16_t len)
|
||||
{
|
||||
u_int16_t t;
|
||||
const u_int8_t *p = _p;
|
||||
const u_int8_t *end = p + len;
|
||||
|
||||
while(p < (end - 1)) {
|
||||
t = (p[0] << 8) + p[1];
|
||||
sum += t;
|
||||
if(sum < t)
|
||||
sum++;
|
||||
p += 2;
|
||||
}
|
||||
if(p < end) {
|
||||
t = (p[0] << 8) + 0;
|
||||
sum += t;
|
||||
if(sum < t)
|
||||
sum++;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static uint16_t
|
||||
chksum(const void *p, uint16_t len)
|
||||
{
|
||||
uint16_t sum = ip4sum(0, p, len);
|
||||
return (sum == 0) ? 0xffff : uip_htons(sum);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
check_ip(const struct ip *ip, unsigned ip_len)
|
||||
{
|
||||
u_int16_t sum, ip_hl;
|
||||
|
||||
if(send_eth) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check IP version and length. */
|
||||
if((ip->ip_vhl & IP_V) != IP_V4) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(uip_ntohs(ip->ip_len) > ip_len) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
if(uip_ntohs(ip->ip_len) < ip_len) {
|
||||
return -3;
|
||||
}
|
||||
|
||||
/* Check IP header. */
|
||||
ip_hl = 4 * (ip->ip_vhl & IP_HL);
|
||||
sum = ip4sum(0, ip, ip_hl);
|
||||
if(sum != 0xffff && sum != 0x0) {
|
||||
return -4;
|
||||
}
|
||||
|
||||
if(ip->ip_p == 6 || ip->ip_p == 17) { /* Check TCP or UDP header. */
|
||||
u_int16_t tcp_len = ip_len - ip_hl;
|
||||
|
||||
/* Sum pseudoheader. */
|
||||
sum = ip->ip_p + tcp_len; /* proto and len, no carry */
|
||||
sum = ip4sum(sum, &ip->ip_src, 8); /* src and dst */
|
||||
|
||||
/* Sum TCP/UDP header and data. */
|
||||
sum = ip4sum(sum, (u_int8_t*)ip + ip_hl, tcp_len);
|
||||
|
||||
/* Failed checksum test? */
|
||||
if(sum != 0xffff && sum != 0x0) {
|
||||
if(ip->ip_p == 6) { /* TCP == 6 */
|
||||
return -5;
|
||||
} else { /* UDP */
|
||||
/* Deal with disabled UDP checksums. */
|
||||
if(ip->uh_sum != 0) {
|
||||
return -6;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(ip->ip_p == 1) { /* ICMP */
|
||||
u_int16_t icmp_len = ip_len - ip_hl;
|
||||
|
||||
sum = ip4sum(0, (u_int8_t*)ip + ip_hl, icmp_len);
|
||||
if(sum != 0xffff && sum != 0x0) {
|
||||
return -7;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* Read a single character from stdin. When we have a full packet, write it to
|
||||
* the network interface.
|
||||
*/
|
||||
void
|
||||
serial_to_wpcap(void)
|
||||
{
|
||||
static union {
|
||||
unsigned char inbuf[2000];
|
||||
struct ip iphdr;
|
||||
} uip;
|
||||
static int inbufptr = 0;
|
||||
|
||||
int ret;
|
||||
unsigned char c;
|
||||
|
||||
if(inbufptr >= sizeof(uip.inbuf)) {
|
||||
inbufptr = 0;
|
||||
return;
|
||||
}
|
||||
ret = read(STDIN_FILENO, &c, 1);
|
||||
|
||||
if(ret <= 0) {
|
||||
err(1, "serial_to_wpcap: read");
|
||||
inbufptr = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (c) {
|
||||
case SLIP_END:
|
||||
if(inbufptr > 0) {
|
||||
/*
|
||||
* Sanity checks.
|
||||
*/
|
||||
#define DEBUG_LINE_MARKER '\r'
|
||||
int ecode;
|
||||
|
||||
ecode = check_ip(&uip.iphdr, inbufptr);
|
||||
if(ecode < 0 && inbufptr == 8
|
||||
&& strncmp((const char*)uip.inbuf, "=IPA", 4) == 0) {
|
||||
static struct in_addr ipa;
|
||||
|
||||
inbufptr = 0;
|
||||
if(memcmp(&ipa, &uip.inbuf[4], sizeof(ipa)) == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(&ipa, &uip.inbuf[4], sizeof(ipa));
|
||||
break;
|
||||
} else if(ecode < 0) {
|
||||
/*
|
||||
* If sensible ASCII string, print it as debug info!
|
||||
*/
|
||||
/* printf("----------------------------------\n");*/
|
||||
if(uip.inbuf[0] == DEBUG_LINE_MARKER) {
|
||||
fwrite(uip.inbuf + 1, inbufptr - 1, 1, stderr);
|
||||
} else if(is_sensible_string(uip.inbuf, inbufptr)) {
|
||||
fwrite(uip.inbuf, inbufptr, 1, stderr);
|
||||
} else {
|
||||
fprintf(stderr, "serial_to_wpcap: drop packet len=%d ecode=%d\n",
|
||||
inbufptr, ecode);
|
||||
}
|
||||
inbufptr = 0;
|
||||
break;
|
||||
}
|
||||
PROGRESS("s");
|
||||
|
||||
if(send_eth) {
|
||||
raw_send(uip.inbuf, inbufptr);
|
||||
} else {
|
||||
/* printf("Sending to wpcap\n");*/
|
||||
if(uip.iphdr.ip_id != last_id) {
|
||||
last_id = uip.iphdr.ip_id;
|
||||
print_packet("to wpcap: ", uip.inbuf, inbufptr);
|
||||
wpcap_send(uip.inbuf, inbufptr);
|
||||
} else {
|
||||
/*print_packet("IGNORED to wpcap: ", uip.inbuf, inbufptr);*/
|
||||
}
|
||||
}
|
||||
/* printf("After sending to wpcap\n");*/
|
||||
inbufptr = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case SLIP_ESC:
|
||||
/* TODO We do not actually check that we have another byte incoming, so
|
||||
* we may block here */
|
||||
read(STDIN_FILENO, &c, 1);
|
||||
|
||||
switch (c) {
|
||||
case SLIP_ESC_END:
|
||||
c = SLIP_END;
|
||||
break;
|
||||
case SLIP_ESC_ESC:
|
||||
c = SLIP_ESC;
|
||||
break;
|
||||
}
|
||||
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
uip.inbuf[inbufptr++] = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
unsigned char stdout_buf[2000];
|
||||
int stdout_buf_cnt;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
stdout_write(unsigned char c)
|
||||
{
|
||||
if(stdout_buf_cnt >= sizeof(stdout_buf)) {
|
||||
err(1, "stdout_write overflow");
|
||||
}
|
||||
stdout_buf[stdout_buf_cnt] = c;
|
||||
stdout_buf_cnt++;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
stdout_buf_empty(void)
|
||||
{
|
||||
return stdout_buf_cnt == 0;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
stdout_flushbuf(void)
|
||||
{
|
||||
if(stdout_buf_empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
fwrite(stdout_buf, stdout_buf_cnt, 1, stdout);
|
||||
stdout_buf_cnt = 0;
|
||||
fflush(stdout);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
write_slip_stdout(void *inbuf, int len)
|
||||
{
|
||||
u_int8_t *p = inbuf;
|
||||
int i, ecode;
|
||||
struct ip *iphdr = inbuf;
|
||||
|
||||
if(!send_eth) {
|
||||
/*
|
||||
* Sanity checks.
|
||||
*/
|
||||
/*fprintf(stderr, "write_slip_stdout: %d\n", len);*/
|
||||
ecode = check_ip(inbuf, len);
|
||||
if(ecode < 0) {
|
||||
fprintf(stderr, "write_slip_stdout: drop packet %d\n", ecode);
|
||||
return;
|
||||
}
|
||||
|
||||
if(iphdr->ip_id == 0 && iphdr->ip_off & IP_DF) {
|
||||
uint16_t nid = uip_htons(ip_id++);
|
||||
iphdr->ip_id = nid;
|
||||
nid = ~nid; /* negate */
|
||||
iphdr->ip_sum += nid; /* add */
|
||||
if(iphdr->ip_sum < nid) { /* 1-complement overflow? */
|
||||
iphdr->ip_sum++;
|
||||
}
|
||||
ecode = check_ip(inbuf, len);
|
||||
if(ecode < 0) {
|
||||
fprintf(stderr, "write_slip_stdout: drop packet %d\n", ecode);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
iphdr->ip_ttl = uip_htons(uip_htons(iphdr->ip_ttl) + 1);
|
||||
if(iphdr->ip_ttl == 0) {
|
||||
fprintf(stderr, "Packet with ttl %d dropped\n", iphdr->ip_ttl);
|
||||
return;
|
||||
}
|
||||
iphdr->ip_sum = 0;
|
||||
iphdr->ip_sum = ~chksum(iphdr, 4 * (iphdr->ip_vhl & IP_HL));
|
||||
ecode = check_ip(inbuf, len);
|
||||
if(ecode < 0) {
|
||||
fprintf(stderr, "write_slip_stdout: drop packet %d\n", ecode);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 0; i < len; i++) {
|
||||
switch (p[i]) {
|
||||
case SLIP_END:
|
||||
stdout_write(SLIP_ESC);
|
||||
stdout_write(SLIP_ESC_END);
|
||||
break;
|
||||
case SLIP_ESC:
|
||||
stdout_write(SLIP_ESC);
|
||||
stdout_write(SLIP_ESC_ESC);
|
||||
break;
|
||||
default:
|
||||
stdout_write(p[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
stdout_write(SLIP_END);
|
||||
/* printf("slip end\n");*/
|
||||
PROGRESS("t");
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*const char *ipaddr;*/
|
||||
/*const char *netmask;*/
|
||||
static int got_sigalarm;
|
||||
void
|
||||
sigalarm(int signo)
|
||||
{
|
||||
got_sigalarm = 1;
|
||||
return;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
sigalarm_reset(void)
|
||||
{
|
||||
#ifdef linux
|
||||
#define TIMEOUT (997*1000)
|
||||
#else
|
||||
#define TIMEOUT (2451*1000)
|
||||
#endif
|
||||
ualarm(TIMEOUT, TIMEOUT);
|
||||
got_sigalarm = 0;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int c;
|
||||
int ret;
|
||||
char buf[4000];
|
||||
int logging = 0;
|
||||
|
||||
ip_id = getpid() * time(NULL);
|
||||
|
||||
while((c = getopt(argc, argv, "E:D:hl:t:T")) != -1) {
|
||||
switch (c) {
|
||||
case 'E':
|
||||
send_eth = 1;
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
should_print = 1;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
logging = 1;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
case 'h':
|
||||
default:
|
||||
err(1,
|
||||
"usage: wpcapstdio [-E] [-l] [-T] <IP address of local Ethernet card> <IP address of SLIP network> <netmask of SLIP network>");
|
||||
break;
|
||||
}
|
||||
}
|
||||
argc -= (optind - 1);
|
||||
argv += (optind - 1);
|
||||
|
||||
if(argc != 4) {
|
||||
err(1, "usage: wpcapstdio [-E] [-T] <IP address of local Ethernet card> <IP address of SLIP network> <netmask of SLIP network>");
|
||||
}
|
||||
|
||||
wpcap_start(argv[1], argv[2], argv[3], logging);
|
||||
stdout_write(SLIP_END);
|
||||
|
||||
atexit(cleanup);
|
||||
signal(SIGHUP, sigcleanup);
|
||||
signal(SIGTERM, sigcleanup);
|
||||
signal(SIGINT, sigcleanup);
|
||||
signal(SIGALRM, sigalarm);
|
||||
|
||||
while(1) {
|
||||
if(got_sigalarm) {
|
||||
/* Send "?IPA". */
|
||||
stdout_write('?');
|
||||
stdout_write('I');
|
||||
stdout_write('P');
|
||||
stdout_write('A');
|
||||
stdout_write(SLIP_END);
|
||||
got_sigalarm = 0;
|
||||
}
|
||||
|
||||
if(stdout_buf_empty()) {
|
||||
char *pbuf = buf;
|
||||
|
||||
ret = wpcap_poll(&pbuf, send_eth);
|
||||
if(ret > 0) {
|
||||
if(send_eth) {
|
||||
write_slip_stdout(pbuf, ret);
|
||||
stdout_flushbuf();
|
||||
} else {
|
||||
struct ip *iphdr = (struct ip *)pbuf;
|
||||
if(iphdr->ip_id != last_id) {
|
||||
/*last_id = iphdr->ip_id;*/
|
||||
print_packet("to stdout: ", (uint8_t*)pbuf, ret);
|
||||
write_slip_stdout(pbuf, ret);
|
||||
stdout_flushbuf();
|
||||
} else {
|
||||
/*print_packet("IGNORED to stdout: ", (uint8_t*)pbuf, ret);*/
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!stdout_buf_empty()) {
|
||||
stdout_flushbuf();
|
||||
}
|
||||
|
||||
{
|
||||
fd_set s_rd;
|
||||
struct timeval tv;
|
||||
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 100;
|
||||
|
||||
do {
|
||||
FD_ZERO(&s_rd);
|
||||
FD_SET(fileno(stdin), &s_rd);
|
||||
select(fileno(stdin) + 1, &s_rd, NULL, NULL, &tv);
|
||||
if(FD_ISSET(fileno(stdin), &s_rd)) {
|
||||
serial_to_wpcap();
|
||||
}
|
||||
} while(FD_ISSET(fileno(stdin), &s_rd));
|
||||
}
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
Loading…
Reference in a new issue