📄 serial_tun.c
字号:
/*
* "Copyright (c) 2008 The Regents of the University of California.
* All rights reserved."
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice, the following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
*
*/
/*
* Copyright (c) 2007 Matus Harvan
* All rights reserved
*
* Copyright (c) 2008 Stephen Dawson-Haggerty
* Extensivly modified to use lib6lowpan / b6lowpan.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * The name of the author may not 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
* OWNER 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#include <stdarg.h>
#include <termios.h>
#include <errno.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <lib6lowpan/TrackFlows.h>
#include <lib6lowpan/6lowpan.h>
#include <lib6lowpan/ip.h>
#include <lib6lowpan/lib6lowpan.h>
#include <lib6lowpan/devconf.h>
#include <lib6lowpan/IEEE154Packet.h>
#include "serialsource.h"
#include "serialpacket.h"
#include "serialprotocol.h"
#include "sfsource.h"
#include "tun_dev.h"
#include "routing.h"
#include "logging.h"
#include "config.h"
#include "nwstate.h"
#include "vty/vty.h"
#define min(a,b) ( (a>b) ? b : a )
#define max(a,b) ( (a>b) ? a : b )
int tun_fd, radvd_fd = -1, fifo_fd = -1, keepalive_needed = 1;
int opt_listenonly = 0, opt_trackflows = 0;
int radvd_init(char *ifname, struct config *c);
void radvd_process();
void radvd_reset_adverts(void);
#ifndef SF_SRC
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)
#define close_pan() close_serial_source(ser_src);
#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)
#define close_pan() close(sf_fd)
#endif
sig_atomic_t do_shutdown = 0;
void driver_shutdown() {
do_shutdown = 1;
}
enum {
N_RECONSTRUCTIONS = 10,
};
/*
*/
#ifdef __TARGET_mips__
const char *def_configfile = "/etc/lowpan/serial_tun.conf";
#else
const char *def_configfile = "serial_tun.conf";
#endif
extern struct in6_addr __my_address;
uint16_t local_seqno = 0;
volatile sig_atomic_t config_success = 0;
struct config driver_config;
char dev[IFNAMSIZ];
struct {
time_t boot_time;
unsigned long tx_pkts;
unsigned long tx_frags;
unsigned long tx_bytes;
unsigned long rx_pkts;
unsigned long rx_frags;
unsigned long rx_bytes;
unsigned long fw_pkts;
} stats = {0, 0, 0, 0, 0, 0, 0, 0};
#ifdef CENTRALIZED_ROUTING
void install_route(struct split_ip_msg *amsg, uint8_t flags);
void uninstall_route(uint16_t n1, uint16_t n2);
#endif
/* ------------------------------------------------------------------------- */
void stderr_msg(serial_source_msg problem)
{
// fprintf(stderr, "Note: %s\n", msgs[problem]);
}
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 plen: %i\n", msg->hdr.nxt_hdr, msg->hdr.hlim, ntohs(msg->hdr.plen));
printf(" src: ");
for (i = 0; i < 16; i++) printf("0x%x ", msg->hdr.ip6_src.s6_addr[i]);
printf("\n");
printf(" dst: ");
for (i = 0; i < 16; i++) printf("0x%x ", msg->hdr.ip6_dst.s6_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");
}
const char *fifo_name = "/var/run/ip-driver/flows";
void fifo_open() {
struct stat stat_buf;
if (opt_trackflows) {
if (stat(fifo_name, &stat_buf) < 0) {
error("fifo does not exist -- track flows will be diabled\n");
return;
}
fifo_fd = open(fifo_name, O_WRONLY | O_NONBLOCK );
if (fifo_fd < 0) {
error("unable to open fifo %i %s: is a reader connected?\n", fifo_fd, fifo_name);
fifo_fd = -1;
return;
}
}
}
void fifo_close() {
if (fifo_fd >= 0) {
close(fifo_fd);
}
}
enum { N_OUTGOING_CACHE = 10, }; int outgoing_cache_idx = 0;
struct flow_id_msg outgoing_cache[N_OUTGOING_CACHE];
void fifo_report(struct split_ip_msg *msg, uint16_t dest, int nxt_hdr) {
if (fifo_fd >= 0) {
outgoing_cache_idx = (outgoing_cache_idx + 1) % N_OUTGOING_CACHE;
outgoing_cache[outgoing_cache_idx].flow = msg->flow_id;
outgoing_cache[outgoing_cache_idx].src = ntohs(msg->hdr.ip6_src.s6_addr16[7]);
outgoing_cache[outgoing_cache_idx].dst = ntohs(msg->hdr.ip6_dst.s6_addr16[7]);
outgoing_cache[outgoing_cache_idx].local_address = ntohs(__my_address.s6_addr16[7]);
outgoing_cache[outgoing_cache_idx].nxt_hdr = nxt_hdr;
outgoing_cache[outgoing_cache_idx].n_attempts = 1;
outgoing_cache[outgoing_cache_idx].attempts[0].next_hop = (dest);
debug("adding cache entry: %i %i\n", outgoing_cache[outgoing_cache_idx].src,
outgoing_cache[outgoing_cache_idx].flow);
}
}
void flow_insert_label(struct split_ip_msg *msg) {
uint8_t *buf;
struct generic_header *g_hdr;
if (opt_trackflows) {
buf = malloc(sizeof(struct ip6_ext) + sizeof(struct tlv_hdr) + sizeof(struct flow_id));
g_hdr = (struct generic_header *)malloc(sizeof(struct generic_header));
struct ip6_ext *ext = (struct ip6_ext *)buf;
struct tlv_hdr *tlv = (struct tlv_hdr *)(ext + 1);
struct flow_id *id = (struct flow_id *)(tlv + 1);
ext->nxt_hdr = msg->hdr.nxt_hdr;
msg->hdr.nxt_hdr = IPV6_HOP;
ext->len = sizeof(struct ip6_ext) + sizeof(struct tlv_hdr) + sizeof(struct flow_id);
tlv->type = TLV_TYPE_FLOW;
tlv->len = ext->len - sizeof(struct ip6_ext);
id->id = msg->flow_id;
g_hdr->payload_malloced = 1;
g_hdr->hdr.ext = ext;
g_hdr->len = ext->len;
g_hdr->next = msg->headers;
msg->headers = g_hdr;
msg->hdr.plen = htons(ntohs(msg->hdr.plen) + ext->len);
}
}
/*
* frees the linked list structs, and their payloads if we have
* malloc'ed them at some other point.
*
* does not free the payload buffer or the actual split_ip_msg struct,
* since those are malloc'ed seperatly in this implementation.
*/
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]);
memset(buf, 0, 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, int cmdno) {
uint8_t buf[sizeof(config_cmd_t) + 1];
config_cmd_t *cmd = (config_cmd_t *)(&buf[1]);
memset(buf, 0, sizeof(config_cmd_t) + 1);
buf[0] = TOS_SERIAL_DEVCONF;
cmd->cmd = cmdno;
cmd->rf.addr = c->router_addr.s6_addr16[7]; // is network byte-order
cmd->rf.channel = c->channel;
cmd->retx.retries = htons(c->retries);
cmd->retx.delay = htons(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, ntohs(rep->addr));
switch (rep->error) {
case CONFIG_ERROR_BOOTED:
configure_setparms(&driver_config, CONFIG_SET_PARM);
break;
default:
info("interface device successfully initialized\n");
config_success = 1;
/* put this here because we already use SIGALRM for the
configure timeout, and radvd needs it for its own timer. */
if (radvd_fd < 0 && (radvd_fd = radvd_init(dev, &driver_config)) < 0) {
fatal("radvd init failed!\n");
exit(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, ieee154_saddr_t dest, uint16_t payload_len) {
IEEE154_header_t *radioPacket = (IEEE154_header_t *)(serial + 1);
radioPacket->length = payload_len + MAC_HEADER_SIZE + MAC_FOOTER_SIZE;
// don't include the length byte
radioPacket->fcf = htons(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;
}
void send_fragments (struct split_ip_msg *msg, ieee154_saddr_t dest) {
int result;
uint16_t frag_len;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -