LQ Newbie
Registered: Nov 2008
Posts: 4
Original Poster
Rep:
|
This a c driver and router for adding an IPv6 over 802.15.4 interface to a linux machine
it's code:
---------------------------------------
#define min(a,b) ( (a>b) ? b : a )
#define max(a,b) ( (a>b) ? a : b )
#if 0
static char *msgs[] = {
"unknown_packet_type",
"ack_timeout",
"sync",
"too_long",
"too_short",
"bad_sync",
"bad_crc",
"closed",
"no_memory",
"unix_error"
};
#endif
int tun_fd;
#ifndef SIM
serial_source ser_src;
#define write_pan_packet(DATA, LEN) write_serial_packet(ser_src, DATA, LEN)
#define read_pan_packet(LENP) read_serial_packet(ser_src, LENP)
#else
int sf_fd;
#define write_pan_packet(DATA, LEN) write_sf_packet(sf_fd, DATA, LEN)
#define read_pan_packet(LENP) read_sf_packet(sf_fd, LENP)
#endif
extern uint8_t multicast_prefix[8];
enum {
TOS_SERIAL_802_15_4_ID = 2,
TOS_SERIAL_DEVCONF = 3,
};
enum {
N_RECONSTRUCTIONS = 10,
};
#ifdef __TARGET_mips__
static char* ifconfig_fmt_global = "ifconfig tun0 add %x%02x:%x%02x:%x%02x:%x%02x:%x%02x:%x%02x:%x%02x:%x%02x/128";
static char* ifconfig_fmt_llocal = "ifconfig tun0 add fe80::%x%02x/64";
char *def_configfile = "/etc/lowpan/serial_tun.conf";
#else
static char* ifconfig_fmt_global = "ifconfig tun0 inet6 add %x%02x:%x%02x:%x%02x:%x%02x:%x%02x:%x%02x:%x%02x:%x%02x/128";
static char* ifconfig_fmt_llocal = "ifconfig tun0 inet6 add fe80::%x%02x/64";
char *def_configfile = "serial_tun.conf";
#endif
extern ip6_addr_t __my_address;
uint16_t local_seqno = 0;
#ifdef DBG_TRACK_FLOWS
FILE *dbg_file;
#endif
volatile sig_atomic_t config_success = 0;
struct config driver_config;
cmpr_ip6_addr_t cmpr_from_IP(ip6_addr_t ip) {
return ((uint16_t)ip[14] << 8) | ip[15];
}
/* ------------------------------------------------------------------------- */
void stderr_msg(serial_source_msg problem)
{
// fprintf(stderr, "Note: %s\n", msgs[problem]);
}
int memclr(uint8_t *buf, int bytes) {
int i;
for (i = 0; i < bytes; i++) {
buf[i] = 0;
}
return 0;
}
/* from contiki-2.x/tools/tunslip.c */
int ssystem(const char *fmt, ...)
{
char cmd[128];
va_list ap;
va_start(ap, fmt);
vsnprintf(cmd, sizeof(cmd), fmt, ap);
va_end(ap);
debug("ssystem: '%s'\n", cmd);
return system(cmd);
}
void print_ip_packet(struct split_ip_msg *msg) {
int i;
struct generic_header *g_hdr;
if (log_getlevel() > LOGLVL_DEBUG) return;
printf(" nxthdr: 0x%x hlim: 0x%x\n", msg->hdr.nxt_hdr, msg->hdr.hlim);
printf(" src: ");
for (i = 0; i < 16; i++) printf("0x%x ", msg->hdr.src_addr[i]);
printf("\n");
printf(" dst: ");
for (i = 0; i < 16; i++) printf("0x%x ", msg->hdr.dst_addr[i]);
printf("\n");
g_hdr = msg->headers;
while (g_hdr != NULL) {
printf("header [%i]: ", g_hdr->len);
for (i = 0; i < g_hdr->len; i++)
printf("0x%x ", g_hdr->hdr.data[i]);
printf("\n");
g_hdr = g_hdr->next;
}
printf("data [%i]:\n\t", msg->data_len);
for (i = 0; i < msg->data_len; i++) {
if (i == 0x40) {
printf (" ...\n");
break;
}
printf("0x%x ", msg->data[i]);
if (i % 16 == 15) printf("\n\t");
if (i % 16 == 7) printf (" ");
}
printf("\n");
}
void free_split_msg(struct split_ip_msg *msg) {
struct generic_header *cur, *next;
cur = msg->headers;
while (cur != NULL) {
next = cur->next;
if (cur->payload_malloced)
free(cur->hdr.data);
free(cur);
cur = next;
}
}
void configure_timeout() {
if (config_success == 0) {
fatal("configuring interface failed! aborting!\n");
exit(2);
} else {
signal(SIGALRM, SIG_DFL);
}
}
void configure_reboot() {
uint8_t buf[sizeof(config_cmd_t) + 1];
config_cmd_t *cmd = (config_cmd_t *)(&buf[1]);
memclr(buf, sizeof(config_cmd_t) + 1);
buf[0] = TOS_SERIAL_DEVCONF;
cmd->cmd = CONFIG_REBOOT;
signal(SIGALRM, configure_timeout);
write_pan_packet(buf, CONFIGURE_MSG_SIZE + 1);
alarm(5);
}
void configure_setparms(struct config *c) {
uint8_t buf[sizeof(config_cmd_t) + 1];
config_cmd_t *cmd = (config_cmd_t *)(&buf[1]);
memclr(buf, sizeof(config_cmd_t) + 1);
buf[0] = TOS_SERIAL_DEVCONF;
cmd->cmd = CONFIG_SET_PARM;
cmd->rf.addr = hton16((((uint16_t)c->router_addr[14]) << 8) | ((uint16_t)c->router_addr[15]));
cmd->rf.channel = c->channel;
cmd->retx.retries = hton16(10);
cmd->retx.delay = hton16(30);
write_pan_packet(buf, CONFIGURE_MSG_SIZE + 1);
}
/* ------------------------------------------------------------------------- */
/*
* the first byte the TOS serial stack sends is a dispatch byte. One
* dispatch value is for forwarded 802;.15.4 packets; we use a few
* others to talk directly to the attached IPBaseStation.
*/
void handle_other_pkt(uint8_t *data, int len) {
config_reply_t *rep;
switch (data[0]) {
case TOS_SERIAL_DEVCONF:
rep = (config_reply_t *)(&data[1]);
debug("interface configured (0x%x) addr: 0x%x\n", rep->error, ntoh16(rep->addr));
switch (rep->error) {
case CONFIG_ERROR_BOOTED:
configure_setparms(&driver_config);
break;
default:
info("interface device successfully initialized\n");
config_success = 1;
}
break;
default:
warn("received serial packet with unknown dispatch 0x%x\n",data[0]);
log_dump_serial_packet(data, len);
}
}
/* ------------------------------------------------------------------------- */
/* handling of data arriving on the tun interface */
void write_radio_header(uint8_t *serial, hw_addr_t dest, uint16_t payload_len) {
#ifndef SIM
IEEE154_header_t *radioPacket = (IEEE154_header_t *)(serial + 1);
radioPacket->length = payload_len + MAC_HEADER_SIZE + MAC_FOOTER_SIZE
#ifdef DBG_TRACK_FLOWS
+ sizeof(struct flow_id);
#else
;
#endif
// don't include the length byte
radioPacket->fcf = hton16(0x4188);
// dsn will get set on mote
radioPacket->destpan = 0;
radioPacket->dest = htole16(dest);
// src will get set on mote
serial[0] = SERIAL_TOS_SERIAL_802_15_4_ID;
#else
serial_header_t *serialHeader = (serial_header_t *)(serial + 1);
serialHeader->length = payload_len
#ifdef DBG_TRACK_FLOWS
+ sizeof(struct flow_id);
#else
;
#endif
serialHeader->dest = hton16(dest);
serialHeader->type = 0;
serial[0] = 0;
#endif
}
void send_fragments (struct split_ip_msg *msg, hw_addr_t dest) {
int result;
uint16_t frag_len;
fragment_t progress;
uint8_t serial[LOWPAN_LINK_MTU + 1];
#ifndef SIM
IEEE154_header_t *radioPacket = (IEEE154_header_t *)(serial + 1);
#define PKTLEN(X) ((X)->length + 2)
#else
serial_header_t *radioPacket = (serial_header_t *)(serial + 1);
#define PKTLEN(X) ((X)->length + sizeof(serial_header_t) + 1)
#endif
uint8_t *lowpan = (uint8_t *)(radioPacket + 1);
#ifdef DBG_TRACK_FLOWS
#define LOWPAN_PAYLOAD_LENGTH (LOWPAN_LINK_MTU - MAC_HEADER_SIZE \
- MAC_FOOTER_SIZE - sizeof(struct flow_id))
lowpan += sizeof(struct flow_id);
#else
#define LOWPAN_PAYLOAD_LENGTH (LOWPAN_LINK_MTU - MAC_HEADER_SIZE \
- MAC_FOOTER_SIZE)
#endif
progress.offset = 0;
// and IEEE 802.15.4 header
// write_radio_header(serial, dest, frag_len);
#ifdef DBG_TRACK_FLOWS
#ifndef SIM
ip_memcpy(serial + 1 + sizeof(IEEE154_header_t), &msg->id, sizeof(struct flow_id));
#else
ip_memcpy(serial + 1 + sizeof(serial_header_t), &msg->id, sizeof(struct flow_id));
#endif
if (dest != 0xffff) {
}
#endif
while ((frag_len = getNextFrag(msg, &progress, lowpan,
LOWPAN_PAYLOAD_LENGTH)) > 0) {
//debug("frag len: 0x%x offset: 0x%x plen: 0x%x\n", frag_len, progress.offset * 8, ntoh16(ip_header->plen));
write_radio_header(serial, dest, frag_len);
// if this is sent too fast, the base station can't keep up. The effect of this is
// we send incomplete fragment. 25ms seems to work pretty well.
// usleep(30000);
// 6-9-08 : SDH : this is a bad fix that does not address the
// problem.
// at the very least, the serial ack's seem to be
// working, so we should be retrying if the ack is failing
// because the hardware cannot keep up.
#ifdef __TARGET_mips__
usleep(50000);
#endif
log_dump_serial_packet(serial, PKTLEN(radioPacket));
result = write_pan_packet(serial, PKTLEN(radioPacket));
if (result != 0)
result = write_pan_packet(serial, PKTLEN(radioPacket));
debug("send_fragments: result: 0x%x len: 0x%x\n", result, frag_len);
log_dump_serial_packet(serial, PKTLEN(radioPacket));
}
}
void icmp_unreachable(struct split_ip_msg *msg) {
}
uint8_t ip_to_pan(struct split_ip_msg *msg) {
uint16_t dest;
debug("ip_to_pan\n");
print_ip_packet(msg);
switch (routing_is_onehop(msg)) {
case ROUTE_MHOP:
debug("Multihop packet");
if (routing_insert_route(msg)) goto fail;
break;
case ROUTE_NO_ROUTE:
info("destination unreachable!\n");
tun_write(tun_fd, msg);
return 0;
}
dest = routing_get_nexthop(msg);
debug("next hop: 0x%x\n", dest);
send_fragments(msg, dest);
return 0;
fail:
error("ip_to_pan: no route to host\n");
return 1;
}
void upd_source_route(struct source_header *sh, hw_addr_t addr) {
if (sh->current < SH_NENTRIES(sh)) {
sh->hops[sh->current] = leton16(addr);
sh->current++;
}
}
int remove_sourceroute(struct split_ip_msg *msg) {
struct source_header *sh;
struct generic_header *g_hdr;
uint8_t removeSource = 1;
if (msg->hdr.nxt_hdr == NXTHDR_SOURCE) {
sh = msg->headers->hdr.sh;
upd_source_route(sh, msg->metadata.sender);
if (cmpPfx(msg->hdr.dst_addr, __my_address) &&
((msg->hdr.dst_addr[14] != __my_address[14] ||
msg->hdr.dst_addr[15] != __my_address[15]))) {
info("Packet with source header not destined for me\n");
if ((sh->dispatch & IP_EXT_SOURCE_INVAL) != IP_EXT_SOURCE_INVAL) {
info("Removing invalid source header\n");
removeSource = 0;
}
if ((sh->dispatch & IP_EXT_SOURCE_CONTROLLER) == IP_EXT_SOURCE_CONTROLLER)
return 1;
}
if (removeSource) {
msg->hdr.nxt_hdr = sh->nxt_hdr;
msg->hdr.plen = hton16(ntoh16(msg->hdr.plen) - sh->len);
g_hdr = msg->headers;
msg->headers = msg->headers->next;
free(g_hdr);
}
}
return 0;
}
void handle_serial_packet(struct split_ip_msg *msg) {
#ifdef DBG_TRACK_FLOWS
uint8_t flags = 0x00;
#endif
if (ntoh16(msg->hdr.plen) > INET_MTU - sizeof(struct ip6_hdr)) {
warn("handle_ip_packet: too long: 0x%x\n", ntoh16(msg->hdr.plen));
return;
}
if (remove_sourceroute(msg))
return;
routing_proc_msg(msg);
remove_sourceroute(msg);
if (cmpPfx(msg->hdr.dst_addr, __my_address) &&
((msg->hdr.dst_addr[14] != __my_address[14] ||
msg->hdr.dst_addr[15] != __my_address[15]))) {
info("Received packet destined to 0x%x\n", msg->hdr.dst_addr[15]);
ip_to_pan(msg);
// do routing
} else {
// give it to linux
// need to remove route info here.
tun_write(tun_fd, msg);
debug("tun_write: wrote 0x%x bytes\n", sizeof(struct ip6_hdr) + ntoh16(msg->hdr.plen));
}
}
void add_header_list(struct split_ip_msg *msg) {
uint8_t nxt_hdr;
struct generic_header *g_hdr, **g_list;
struct ip6_ext *ext = (struct ip6_ext *)msg->next;
uint16_t hdr_len = 0;
debug("add_header_list for message destined to 0x%x\n", msg->hdr.dst_addr[15]);
nxt_hdr = msg->hdr.nxt_hdr;
msg->headers = NULL;
g_list = &(msg->headers);
while (KNOWN_HEADER(nxt_hdr)) {
g_hdr = (struct generic_header *)malloc(sizeof(struct generic_header));
g_hdr->payload_malloced = 0;
g_hdr->hdr.ext = ext;
g_hdr->next = NULL;
*g_list = g_hdr;
g_list = &g_hdr->next;
switch(nxt_hdr) {
case IANA_UDP:
// a UDP header terminates a chain of headers we can compress...
g_hdr->len = sizeof(struct udp_hdr);
ext = (struct ip6_ext *)(((uint8_t *)ext) + sizeof(struct udp_hdr));
nxt_hdr = NXTHDR_UNKNOWN;
break;
// XXX : SDH : these are all "ip extension" headers and so can be treated genericlly.
case NXTHDR_INSTALL:
info("inserted NXTHDR_INSTALL\n");
case NXTHDR_TOPO:
case NXTHDR_SOURCE:
g_hdr->len = ext->len;
nxt_hdr = ext->nxt_hdr;
ext = (struct ip6_ext *)(((uint8_t *)ext) + ext->len);
break;
default:
break;
}
hdr_len += g_hdr->len;
}
msg->data = (uint8_t *)ext;
msg->data_len = ntoh16(msg->hdr.plen) - hdr_len;
}
int tun_input()
{
uint8_t buf[sizeof(struct split_ip_msg) + INET_MTU];
struct split_ip_msg *msg = (struct split_ip_msg *)buf;
int len;
len = tun_read(tun_fd, (void *)(&msg->pi), INET_MTU + sizeof(struct ip6_hdr));
if (len <= 0) {
return 0;
}
debug("tun_read: read 0x%x bytes\n", len);
if ((msg->hdr.vlfc[0] >> 4) != IPV6_VERSION) {
warn("tun_read: discarding non-ip packet\n");
goto fail;
}
if (ntoh16(msg->hdr.plen) > INET_MTU - sizeof(struct ip6_hdr)) {
goto fail;
}
if (msg->hdr.nxt_hdr == 0) {
goto fail;
}
add_header_list(msg);
#ifdef DBG_TRACK_FLOWS
msg->id.src = 100;
msg->id.dst = cmpr_from_IP(msg->hdr.dst_addr);
msg->id.id = local_seqno++;
msg->id.seq = 0;
msg->id.nxt_hdr = msg->hdr.nxt_hdr;
#endif
ip_to_pan(msg);
free_split_msg(msg);
return 1;
fail:
return 1;
}
reconstruct_t reconstructions [N_RECONSTRUCTIONS];
void age_reconstructions() {
int i;
for (i = 0; i < N_RECONSTRUCTIONS; i++) {
// switch "active" buffers to "zombie"
if (reconstructions[i].timeout == T_ACTIVE) {
reconstructions[i].timeout = T_ZOMBIE;
} else if (reconstructions[i].timeout == T_ZOMBIE) {
reconstructions[i].timeout = T_UNUSED;
free(reconstructions[i].buf);
reconstructions[i].buf = NULL;
}
}
}
reconstruct_t *getReassembly(packed_lowmsg_t *lowmsg) {
int i, free_spot = N_RECONSTRUCTIONS + 1;
uint16_t mytag, size;
if (getFragDgramTag(lowmsg, &mytag)) return NULL;
if (getFragDgramSize(lowmsg, &size)) return NULL;
for (i = 0; i < N_RECONSTRUCTIONS; i++) {
if (reconstructions[i].timeout > T_UNUSED && reconstructions[i].tag == mytag) {
reconstructions[i].timeout = T_ACTIVE;
return &(reconstructions[i]);
}
if (reconstructions[i].timeout == T_UNUSED) free_spot = i;
}
if (free_spot != N_RECONSTRUCTIONS + 1) {
reconstructions[free_spot].tag = mytag;
reconstructions[free_spot].size = size;
reconstructions[free_spot].buf = malloc(size + offsetof(struct split_ip_msg, hdr));
reconstructions[free_spot].bytes_rcvd = 0;
reconstructions[free_spot].timeout = T_ACTIVE;
debug("checking buffer size 0x%x\n", reconstructions[free_spot].size);
if (reconstructions[free_spot].buf == NULL) {
reconstructions[free_spot].timeout = T_UNUSED;
return NULL;
}
return &(reconstructions[free_spot]);
}
return NULL;
}
/*
* read data on serial port and send it to the tun interface
* does fragment reassembly
*/
int serial_input() {
packed_lowmsg_t pkt;
reconstruct_t *recon;
struct split_ip_msg *msg;
#ifndef SIM
IEEE154_header_t *mac_hdr;
#else
serial_header_t *mac_hdr;
#endif
uint8_t *ser_data = NULL; /* data read from serial port */
int ser_len = 0; /* length of data read from serial port */
uint8_t shortMsg[INET_MTU];
uint8_t *payload;
#ifdef DBG_TRACK_FLOWS
struct flow_id *fl_id;
#endif
int rv = 1;
/* read data from serial port */
ser_data = (uint8_t *)read_pan_packet(&ser_len);
/* process the packet we have received */
if (ser_len && ser_data) {
#ifndef SIM
if (ser_data[0] != TOS_SERIAL_802_15_4_ID) {
handle_other_pkt(ser_data, ser_len);
goto discard_packet;
}
mac_hdr = (IEEE154_header_t *)(ser_data + 1);
#ifdef DBG_TRACK_FLOWS
fl_id = (struct flow_id *)(ser_data + 1 + sizeof(IEEE154_header_t));
pkt.len = mac_hdr->length - MAC_HEADER_SIZE - MAC_FOOTER_SIZE - sizeof(struct flow_id);
pkt.data = ser_data + 1 + sizeof(IEEE154_header_t) + sizeof(struct flow_id);
#else
pkt.len = mac_hdr->length - MAC_HEADER_SIZE - MAC_FOOTER_SIZE;
pkt.data = ser_data + 1 + sizeof(IEEE154_header_t);
#endif // DBG_TRACK_FLOWS
pkt.src = mac_hdr->src;
pkt.dst = mac_hdr->dest;
#else
mac_hdr = (serial_header_t *)(ser_data + 1);
if (mac_hdr->type != 0) {
goto discard_packet;
}
#ifdef DBG_TRACK_FLOWS
fl_id = (struct flow_id *)(ser_data + 1 + sizeof(serial_header_t));
pkt.len = mac_hdr->length - sizeof(struct flow_id);
pkt.data = ser_data + 1 + sizeof(serial_header_t) + sizeof(struct flow_id);
#else
pkt.len = mac_hdr->length;;
pkt.data = ser_data + 1 + sizeof(serial_header_t);
#endif // DBG_TRACK_FLOWS
// except in serial packets, they __are__ little endian...
pkt.src = ntoh16(mac_hdr->src);
pkt.dst = ntoh16(mac_hdr->dest);
#endif
debug("serial_input: read 0x%x bytes\n", ser_len);
pkt.headers = getHeaderBitmap(&pkt);
if (pkt.headers == LOWPAN_NALP_PATTERN) goto discard_packet;
if (hasFrag1Header(&pkt) || hasFragNHeader(&pkt)) {
unpack_info_t u_info;
uint8_t amount_here;
recon = getReassembly(&pkt);
if (recon == NULL || recon->buf == NULL) goto discard_packet;
msg = (struct split_ip_msg *)recon->buf;
if (hasFrag1Header(&pkt)) {
if (unpackHeaders(&pkt, &u_info,
(uint8_t *)&msg->hdr, recon->size) == NULL) goto discard_packet;
amount_here = pkt.len - (u_info.payload_start - pkt.data);
ip_memcpy(u_info.header_end, u_info.payload_start, amount_here);
recon->bytes_rcvd = sizeof(struct ip6_hdr) + u_info.payload_offset + amount_here;
} else {
uint8_t offset_cmpr;
uint16_t offset;
if (getFragDgramOffset(&pkt, &offset_cmpr)) goto discard_packet;
offset = offset_cmpr * 8;
payload = getLowpanPayload(&pkt);
amount_here = pkt.len - (payload - pkt.data);
if (offset + amount_here > recon->size) goto discard_packet;
ip_memcpy(((uint8_t *)&msg->hdr) + offset, payload, amount_here);
recon->bytes_rcvd += amount_here;
if (recon->size == recon->bytes_rcvd) {
// got all the fragments...
debug ("serial: reconstruction finished\n");
add_header_list(msg);
msg->metadata.sender = pkt.src;
handle_serial_packet(msg);
recon->timeout = T_UNUSED;
free_split_msg(msg);
free(recon->buf);
}
}
} else {
unpack_info_t u_info;
u_info.rih = NULL;
msg = (struct split_ip_msg *)shortMsg;
if (unpackHeaders(&pkt, &u_info,
(uint8_t *)&msg->hdr, INET_MTU) == NULL) goto discard_packet;
if (ntoh16(msg->hdr.plen) > INET_MTU - sizeof(struct ip6_hdr)) goto discard_packet;
msg->metadata.sender = pkt.src;
ip_memcpy(u_info.header_end, u_info.payload_start, ntoh16(msg->hdr.plen));
#ifdef DBG_TRACK_FLOWS
ip_memcpy(&msg->id, fl_id, sizeof(struct flow_id));
#endif
add_header_list(msg);
handle_serial_packet(msg);
free_split_msg(msg);
}
} else {
//printf("no data on serial port, but FD triggered select\n");
rv = 0;
}
discard_packet:
// debug("serial_input: discard packet\n");
free(ser_data);
return rv;
}
/* shifts data between the serial port and the tun interface */
int serial_tunnel(int tun_fd)
{
//int result;
fd_set fs;
time_t last_aging, current_time;
time(&last_aging);
#ifndef SIM
int pan_fd = serial_source_fd(ser_src);
#else
int pan_fd = sf_fd;
#endif
while (1) {
FD_ZERO(&fs);
FD_SET(tun_fd, &fs);
FD_SET(pan_fd, &fs);
select(tun_fd > pan_fd ?
tun_fd + 1 : pan_fd + 1,
&fs, NULL, NULL, NULL);
/* data available on tunnel device */
// this is a better way of polling; this way we will alternate
// between reading from the tun and reading from the device.
// Under heavy load, this is less likely to cause queue drops
// in the kernel, because we are essentially doing a simple
// version of round-robin scheduling.
if (FD_ISSET(tun_fd, &fs))
while(tun_input());
if (FD_ISSET(pan_fd, &fs))
while(serial_input());
#ifndef SIM
if (tcdrain(pan_fd) < 0) {
fatal("tcdrain error: %i\n", errno);
exit(3);
}
#endif
/* end of data available */
time(¤t_time);
if (current_time > last_aging + (FRAG_EXPIRE_TIME / 1024)) {
last_aging = current_time;
age_reconstructions();
}
}
/* end of while(1) */
return 0;
}
#ifdef DBG_TRACK_FLOWS
void truncate_dbg() {
ftruncate(fileno(dbg_file), 0);
}
#endif
int main(int argc, char **argv)
{
char cmd_buf[300];
char dev[DEV_LEN];
int i, c;
while ((c = getopt(argc, argv, "c:")) != -1) {
switch (c) {
case 'c':
def_configfile = optarg;
break;
default:
fatal("Invalid command line arguments.\n");
exit(1);
}
}
log_init();
if (argc - optind != 2) {
#ifndef SIM
fatal("usage: %s [-c config] <device> <rate>\n", argv[0]);
#else
fatal("usage: %s [-c config] <host> <port>\n", argv[0]);
#endif
exit(2);
}
#ifdef DBG_TRACK_FLOWS
dbg_file = fopen("dbg.txt", "w");
if (dbg_file == NULL) {
perror("main: opening dbg file:");
exit(1);
}
// signal(SIGUSR2, truncate_dbg);
#endif
if (config_parse(def_configfile, &driver_config) != 0) {
fatal ("config parse of %s failed!\n", def_configfile);
exit(1);
}
/* create the tunnel device */
dev[0] = 0;
tun_fd = tun_open(dev);
if (tun_fd < 1) {
fatal("Could not create tunnel device. Fatal.\n");
return 1;
} else {
info("created tunnel device: %s\n", dev);
}
for (i = 0; i < N_RECONSTRUCTIONS; i++) {
reconstructions[i].timeout = T_UNUSED;
}
/* open the serial port */
#ifndef SIM
ser_src = open_serial_source(argv[optind], platform_baud_rate(argv[optind + 1]),
1, stderr_msg);
if (!ser_src) {
fatal("Couldn't open serial port at %s:%s\n", argv[optind], argv[optind + 1]);
exit(1);
}
#else
sf_fd = open_sf_source(argv[optind], atoi(argv[optind + 1]));
if (sf_fd < 0) {
fatal("Couldn't connect to serial forwarder sf@%s:%s\n", argv[optind], argv[optind + 1]);
exit(1);
}
#endif
/* 0 - blocking reads
* 1 - non-blocking reads
*/
globalPrefix = 1;
memcpy(__my_address, driver_config.router_addr, 16);
/* set up the tun interface */
ssystem("ifconfig tun0 up");
ssystem("ifconfig tun0 mtu 1280");
sprintf(cmd_buf, ifconfig_fmt_global,
__my_address[0],__my_address[1],__my_address[2],__my_address[3],
__my_address[4],__my_address[5],__my_address[6],__my_address[7],
__my_address[8],__my_address[9],__my_address[10],__my_address[11],
__my_address[12],__my_address[13],__my_address[14],__my_address[15]);
ssystem(cmd_buf);
sprintf(cmd_buf, ifconfig_fmt_llocal,
__my_address[14], __my_address[15]);
ssystem(cmd_buf);
info("send me SIGUSR1 to dump the topology to a 'nwgraph.dot' in the cwd\n");
// info("send me SIGUSR2 to recompute and print source routes to every router\n");
routing_init(&driver_config, dev);
#ifndef SIM
configure_reboot();
#endif
/* start tunneling */
serial_tunnel(tun_fd);
/* clean up */
// close_serial_source(ser_src);
//close(ser_fd);
tun_close(tun_fd, dev);
|