Java code to let Cooja connect to a serial port

This commit is contained in:
Adam Dunkels 2015-03-24 14:44:44 +01:00
parent 64bae5b38d
commit fb64e64ae2
8 changed files with 1309 additions and 48 deletions

View 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);
}
}

View 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);
}
}

View file

@ -1,12 +1,21 @@
CONTIKI=../.. 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 vpath %.c $(CONTIKI)/core/net
wpcapslip: wpcapslip.o wpcap.o tcpdump.o wpcapslip: wpcapslip.o wpcap.o tcpdump.o
wpcapstdio: wpcapstdio.o wpcap.o tcpdump.o
%: %.o %: %.o
$(CC) $(LDFLAGS) $^ /lib/w32api/libws2_32.a /lib/w32api/libiphlpapi.a -o $@ $(CC) $(LDFLAGS) $^ /lib/w32api/libws2_32.a /lib/w32api/libiphlpapi.a -o $@
clean:
rm -f *.class *.exe *.o

View 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
View 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;
}
/*---------------------------------------------------------------------------*/

View file

@ -58,7 +58,6 @@
#include <unistd.h> #include <unistd.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h>
#include <signal.h> #include <signal.h>
#include <termios.h> #include <termios.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
@ -69,7 +68,7 @@
#define PROGRESS(x) #define PROGRESS(x)
static void raw_send(void *buf, int len); void raw_send(void *buf, int len);
struct pcap; struct pcap;
@ -150,7 +149,7 @@ struct arp_entry {
struct uip_eth_addr ethaddr; struct uip_eth_addr ethaddr;
uint8_t time; 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 uip_ipaddr_t all_zeroes_addr = { { 0x0, /* rest is 0 */ } };
static const struct uip_eth_addr broadcast_ethaddr = static const struct uip_eth_addr broadcast_ethaddr =
{{0xff,0xff,0xff,0xff,0xff,0xff}}; {{0xff,0xff,0xff,0xff,0xff,0xff}};
@ -164,18 +163,20 @@ static int arptime;
static int logging; static int logging;
uip_lladdr_t uip_lladdr;
static void static void
log_message(char *msg1, char *msg2) log_message(char *msg1, char *msg2)
{ {
if(logging) { if(logging) {
printf("Log: %s %s\n", msg1, msg2); fprintf(stderr, "Log: %s %s\n", msg1, msg2);
} }
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static void static void
error_exit(char *msg1) error_exit(char *msg1)
{ {
printf("error_exit: %s", msg1); fprintf(stderr, "error_exit: %s", msg1);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
@ -198,11 +199,11 @@ init_pcap(struct in_addr addr)
paddr != NULL; paddr != NULL;
paddr = paddr->next) { paddr = paddr->next) {
if(paddr->addr != NULL && paddr->addr->sa_family == AF_INET) { if(paddr->addr != NULL && paddr->addr->sa_family == AF_INET) {
struct in_addr interface_addr; struct in_addr interface_addr;
interface_addr = ((struct sockaddr_in *)paddr->addr)->sin_addr; interface_addr = ((struct sockaddr_in *)paddr->addr)->sin_addr;
log_message("init_pcap: with address: ", inet_ntoa(interface_addr)); log_message("init_pcap: with address: ", inet_ntoa(interface_addr));
if(interface_addr.s_addr == addr.s_addr) { if(interface_addr.s_addr == addr.s_addr) {
pcap = pcap_open_live(interfaces->name, BUFSIZE, 0, -1, error); pcap = pcap_open_live(interfaces->name, BUFSIZE, 0, -1, error);
if(pcap == NULL) { if(pcap == NULL) {
@ -263,7 +264,7 @@ set_ethaddr(struct in_addr addr)
log_message("set_ethaddr: with address: ", inet_ntoa(adapter_addr)); log_message("set_ethaddr: with address: ", inet_ntoa(adapter_addr));
if(adapter_addr.s_addr == addr.s_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)); inet_ntoa(adapter_addr));
if(adapters->PhysicalAddressLength != 6) { if(adapters->PhysicalAddressLength != 6) {
error_exit("ip addr specified on cmdline does not belong to an ethernet card\n"); 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; int i;
for(i = 0; i < len; ++i) { for(i = 0; i < len; ++i) {
printf("0x%02x, ", buf[i]); fprintf(stderr, "0x%02x, ", buf[i]);
if(i % 8 == 7) { if(i % 8 == 7) {
printf("\n"); fprintf(stderr, "\n");
} }
} }
printf("\n\n"); fprintf(stderr, "\n\n");
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static void static void
@ -305,7 +306,7 @@ uip_arp_update(uip_ipaddr_t *ipaddr, struct uip_eth_addr *ethaddr)
{ {
struct arp_entry *tabptr; struct arp_entry *tabptr;
int i, tmpage, c; int i, tmpage, c;
/* Walk through the ARP mapping table and try to find an entry to /* Walk through the ARP mapping table and try to find an entry to
update. If none is found, the IP -> MAC address mapping is update. If none is found, the IP -> MAC address mapping is
inserted in the ARP table. */ inserted in the ARP table. */
@ -318,7 +319,7 @@ uip_arp_update(uip_ipaddr_t *ipaddr, struct uip_eth_addr *ethaddr)
/* Check if the source IP address of the incoming packet matches /* Check if the source IP address of the incoming packet matches
the IP address in this ARP table entry. */ the IP address in this ARP table entry. */
if(uip_ipaddr_cmp(ipaddr, &tabptr->ipaddr)) { if(uip_ipaddr_cmp(ipaddr, &tabptr->ipaddr)) {
/* An old entry found, update this and return. */ /* An old entry found, update this and return. */
memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6); memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6);
tabptr->time = arptime; tabptr->time = arptime;
@ -399,7 +400,7 @@ arp_out(struct ethip_hdr *iphdr, int len)
int i; int i;
#endif #endif
#if 1 #if 0
/* Find the destination IP address in the ARP table and construct /* Find the destination IP address in the ARP table and construct
the Ethernet header. If the destination IP addres isn't on the the Ethernet header. If the destination IP addres isn't on the
local network, we use the default router's IP address instead. local network, we use the default router's IP address instead.
@ -425,7 +426,7 @@ arp_out(struct ethip_hdr *iphdr, int len)
/* Else, we use the destination IP address. */ /* Else, we use the destination IP address. */
uip_ipaddr_copy(&ipaddr, &iphdr->destipaddr); uip_ipaddr_copy(&ipaddr, &iphdr->destipaddr);
} }
for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
tabptr = &arp_table[i]; tabptr = &arp_table[i];
if(uip_ipaddr_cmp(&ipaddr, &tabptr->ipaddr)) { if(uip_ipaddr_cmp(&ipaddr, &tabptr->ipaddr)) {
@ -439,9 +440,9 @@ arp_out(struct ethip_hdr *iphdr, int len)
memset(arphdr->ethhdr.dest.addr, 0xff, 6); memset(arphdr->ethhdr.dest.addr, 0xff, 6);
memset(arphdr->dhwaddr.addr, 0x00, 6); memset(arphdr->dhwaddr.addr, 0x00, 6);
memcpy(arphdr->ethhdr.src.addr, uip_lladdr.addr, 6); memcpy(arphdr->ethhdr.src.addr, uip_ethaddr.addr, 6);
memcpy(arphdr->shwaddr.addr, uip_lladdr.addr, 6); memcpy(arphdr->shwaddr.addr, uip_ethaddr.addr, 6);
uip_ipaddr_copy(&arphdr->dipaddr, &ipaddr); uip_ipaddr_copy(&arphdr->dipaddr, &ipaddr);
uip_ipaddr_copy(&arphdr->sipaddr, &netaddr); uip_ipaddr_copy(&arphdr->sipaddr, &netaddr);
arphdr->opcode = UIP_HTONS(ARP_REQUEST); /* ARP request. */ arphdr->opcode = UIP_HTONS(ARP_REQUEST); /* ARP request. */
@ -476,27 +477,27 @@ do_arp(void *buf, int len)
if(hdr->ethhdr.type == UIP_HTONS(UIP_ETHTYPE_ARP)) { if(hdr->ethhdr.type == UIP_HTONS(UIP_ETHTYPE_ARP)) {
if(hdr->opcode == UIP_HTONS(ARP_REQUEST)) { if(hdr->opcode == UIP_HTONS(ARP_REQUEST)) {
/* Check if the ARP is for our network */ /* 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(&hdr->dipaddr),
uip_ipaddr_to_quad(&netaddr), uip_ipaddr_to_quad(&netaddr),
uip_ipaddr_to_quad(&netmask));*/ uip_ipaddr_to_quad(&netmask));*/
if(uip_ipaddr_maskcmp(&hdr->dipaddr, &netaddr, &netmask)) { if(uip_ipaddr_maskcmp(&hdr->dipaddr, &netaddr, &netmask)) {
uip_ipaddr_t tmpaddr; uip_ipaddr_t tmpaddr;
/* printf("ARP for us.\n");*/ /* fprintf(stderr, "ARP for us.\n");*/
uip_arp_update(&hdr->sipaddr, &hdr->shwaddr); uip_arp_update(&hdr->sipaddr, &hdr->shwaddr);
hdr->opcode = UIP_HTONS(ARP_REPLY); hdr->opcode = UIP_HTONS(ARP_REPLY);
memcpy(&hdr->dhwaddr.addr, &hdr->shwaddr.addr, 6); memcpy(&hdr->dhwaddr.addr, &hdr->shwaddr.addr, 6);
memcpy(&hdr->shwaddr.addr, &uip_lladdr.addr, 6); memcpy(&hdr->shwaddr.addr, &uip_lladdr.addr, 6);
memcpy(&hdr->ethhdr.src.addr, &uip_lladdr.addr, 6); memcpy(&hdr->ethhdr.src.addr, &uip_lladdr.addr, 6);
memcpy(&hdr->ethhdr.dest.addr, &hdr->dhwaddr.addr, 6); memcpy(&hdr->ethhdr.dest.addr, &hdr->dhwaddr.addr, 6);
uip_ipaddr_copy(&tmpaddr, &hdr->dipaddr); uip_ipaddr_copy(&tmpaddr, &hdr->dipaddr);
uip_ipaddr_copy(&hdr->dipaddr, &hdr->sipaddr); uip_ipaddr_copy(&hdr->dipaddr, &hdr->sipaddr);
uip_ipaddr_copy(&hdr->sipaddr, &tmpaddr); uip_ipaddr_copy(&hdr->sipaddr, &tmpaddr);
hdr->ethhdr.type = UIP_HTONS(UIP_ETHTYPE_ARP); hdr->ethhdr.type = UIP_HTONS(UIP_ETHTYPE_ARP);
raw_send(hdr, sizeof(struct arp_hdr)); raw_send(hdr, sizeof(struct arp_hdr));
return NULL; return NULL;
@ -521,8 +522,8 @@ cleanup(void)
char buf[1024]; char buf[1024];
snprintf(buf, sizeof(buf), "route delete %d.%d.%d.%d", snprintf(buf, sizeof(buf), "route delete %d.%d.%d.%d",
uip_ipaddr_to_quad(&ifaddr)); uip_ipaddr_to_quad(&netaddr));
printf("%s\n", buf); fprintf(stderr, "%s\n", buf);
system(buf); system(buf);
} }
@ -540,9 +541,9 @@ wpcap_start(char *ethcardaddr, char *slipnetaddr, char *slipnetmask, int log)
struct in_addr addr; struct in_addr addr;
char buf[4000]; char buf[4000];
uint32_t tmpaddr; uint32_t tmpaddr;
logging = log; logging = log;
addr.s_addr = inet_addr(ethcardaddr); addr.s_addr = inet_addr(ethcardaddr);
tmpaddr = inet_addr(ethcardaddr); tmpaddr = inet_addr(ethcardaddr);
memcpy(&ifaddr.u16[0], &tmpaddr, sizeof(tmpaddr)); memcpy(&ifaddr.u16[0], &tmpaddr, sizeof(tmpaddr));
@ -551,21 +552,21 @@ wpcap_start(char *ethcardaddr, char *slipnetaddr, char *slipnetmask, int log)
tmpaddr = inet_addr(slipnetmask); tmpaddr = inet_addr(slipnetmask);
memcpy(&netmask.u16[0], &tmpaddr, sizeof(tmpaddr)); 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(&netaddr),
uip_ipaddr_to_quad(&netmask)); uip_ipaddr_to_quad(&netmask));
snprintf(buf, sizeof(buf), "route add %d.%d.%d.%d mask %d.%d.%d.%d %d.%d.%d.%d", snprintf(buf, sizeof(buf), "route add %d.%d.%d.%d mask %d.%d.%d.%d %d.%d.%d.%d",
uip_ipaddr_to_quad(&netaddr), uip_ipaddr_to_quad(&netaddr),
uip_ipaddr_to_quad(&netmask), uip_ipaddr_to_quad(&netmask),
uip_ipaddr_to_quad(&ifaddr)); uip_ipaddr_to_quad(&ifaddr));
printf("%s\n", buf); fprintf(stderr, "%s\n", buf);
system(buf); system(buf);
signal(SIGTERM, remove_route); signal(SIGTERM, remove_route);
log_message("wpcap_init: cmdline address: ", inet_ntoa(addr)); log_message("wpcap_init: cmdline address: ", inet_ntoa(addr));
wpcap = LoadLibrary("wpcap.dll"); wpcap = LoadLibrary("wpcap.dll");
pcap_findalldevs = (int (*)(struct pcap_if **, char *)) pcap_findalldevs = (int (*)(struct pcap_if **, char *))
GetProcAddress(wpcap, "pcap_findalldevs"); GetProcAddress(wpcap, "pcap_findalldevs");
@ -588,12 +589,12 @@ wpcap_start(char *ethcardaddr, char *slipnetaddr, char *slipnetmask, int log)
#if 0 #if 0
while(1) { while(1) {
int ret; int ret;
ret = wpcap_poll(buf); ret = wpcap_poll(buf);
if(ret > 0) { if(ret > 0) {
/* print_packet(buf, ret);*/ /* print_packet(buf, ret);*/
if(do_arp(buf, ret)) { if(do_arp(buf, ret)) {
printf("IP packet\n"); fprintf(stderr, "IP packet\n");
} }
} }
sleep(1); sleep(1);
@ -602,17 +603,16 @@ wpcap_start(char *ethcardaddr, char *slipnetaddr, char *slipnetmask, int log)
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
uint16_t uint16_t
wpcap_poll(char **buf) wpcap_poll(char **buf, int eth)
{ {
struct pcap_pkthdr *packet_header; struct pcap_pkthdr *packet_header;
unsigned char *packet; unsigned char *packet;
int len; int len;
int ret;
char *buf2; char *buf2;
switch(pcap_next_ex(pcap, &packet_header, &packet)) { ret = pcap_next_ex(pcap, &packet_header, &packet);
case -1: if (ret != 1) {
error_exit("error on poll\n");
case 0:
return 0; return 0;
} }
@ -622,13 +622,20 @@ wpcap_poll(char **buf)
CopyMemory(*buf, packet, packet_header->caplen); CopyMemory(*buf, packet, packet_header->caplen);
len = 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); buf2 = do_arp(*buf, len);
if(buf2 == NULL) { if(buf2 == NULL) {
return 0; return 0;
} else { } else {
len = len - (buf2 - *buf); len = len - (buf2 - *buf);
*buf = buf2; *buf = buf2;
/*fprintf(stderr, "wpcap_poll() %d\n", len);*/
return len; return len;
} }
} }
@ -644,7 +651,7 @@ wpcap_send(void *buf, int len)
raw_send(buf2, len); raw_send(buf2, len);
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static void void
raw_send(void *buf, int len) raw_send(void *buf, int len)
{ {
/* printf("sending len %d\n", len);*/ /* printf("sending len %d\n", len);*/

View file

@ -47,8 +47,6 @@
#include <stdarg.h> #include <stdarg.h>
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include <sys/types.h>
#include <sys/select.h>
#include <unistd.h> #include <unistd.h>
#include <errno.h> #include <errno.h>
@ -75,6 +73,18 @@ static int should_print = 0;
#define IP_HLEN 20 #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 static void
print_packet(uint8_t *packet, int len) print_packet(uint8_t *packet, int len)
@ -289,8 +299,9 @@ serial_to_wpcap(FILE *inslip)
*/ */
#define DEBUG_LINE_MARKER '\r' #define DEBUG_LINE_MARKER '\r'
int ecode; int ecode;
ecode = check_ip(&uip.iphdr, inbufptr); 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; static struct in_addr ipa;
inbufptr = 0; inbufptr = 0;
@ -902,7 +913,7 @@ main(int argc, char **argv)
if(iphdr->ip_id != last_id) { if(iphdr->ip_id != last_id) {
last_id = iphdr->ip_id; last_id = iphdr->ip_id;
/* printf("------ wpcap_poll ret %d\n", ret);*/ /* printf("------ wpcap_poll ret %d\n", ret);*/
print_packet(pbuf, ret); print_packet((uint8_t*)pbuf, ret);
write_to_serial(slipfd, pbuf, ret); write_to_serial(slipfd, pbuf, ret);
slip_flushbuf(slipfd); slip_flushbuf(slipfd);
sigalarm_reset(); sigalarm_reset();

View 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));
}
}
}
/*---------------------------------------------------------------------------*/