⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serial_tun.c

📁 tinyos-2.x.rar
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * Copyright (c) 2007 Matus Harvan
 * All rights reserved
 *
 * 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 <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <netdb.h>

#include <stdarg.h>

#include "tun_dev.h"
#include "serialsource.h"
#include "serialpacket.h"
#include "6lowpan.h"

#define min(a,b) ( (a>b) ? b : a )
#define max(a,b) ( (a>b) ? a : b )

static char *msgs[] = {
  "unknown_packet_type",
  "ack_timeout"	,
  "sync"	,
  "too_long"	,
  "too_short"	,
  "bad_sync"	,
  "bad_crc"	,
  "closed"	,
  "no_memory"	,
  "unix_error"
};

/* global variables */
lowpan_pkt_t *fragments = NULL; /* fragment reassembly of received frames */
//lowpan_pkt_t *send_queue = NULL;
int g_send_pending = 0;

hw_addr_t hw_addr;

serial_source ser_src;
int tun_fd = 0; /* tunnel device */
//int ser_fd = 0; /* serial device */

uint16_t g_dgram_tag = 0; /* datagram_tag for sending fragmented packets */

/* ------------------------------------------------------------------------- */
/* function pre-declarations */
int serial_output_am_payload(uint8_t *buf, int len,
			     const hw_addr_t *hw_src_addr,
			     const hw_addr_t *hw_dst_addr);

int serial_input_layer3(uint8_t *buf, int len,
			const hw_addr_t *hw_src_addr,
			const hw_addr_t *hw_dst_addr);

int serial_input_ipv6_uncompressed(uint8_t *buf, int len,
				   const hw_addr_t *hw_src_addr,
				   const hw_addr_t *hw_dst_addr);

int serial_input_ipv6_compressed(uint8_t *buf, int len,
				 const hw_addr_t *hw_src_addr,
				 const hw_addr_t *hw_dst_addr);

/* ------------------------------------------------------------------------- */
/* utility functions */
int get_ser_fd()
{
    return serial_source_fd(ser_src);
}

void increment_g_dgram_tag()
{
    uint16_t tmp = ntohs(g_dgram_tag);
    if (tmp == 0xFFFF) {
	tmp = 0;
    } else {
	tmp++;
    }
    g_dgram_tag = htons(tmp);
}

void stderr_msg(serial_source_msg problem)
{
  fprintf(stderr, "Note: %s\n", msgs[problem]);
}

int
debug(const char *fmt, ...)
{
    int result;
    va_list ap;
    va_start(ap, fmt);
    result = vfprintf(stderr, fmt, ap);
    va_end(ap);
    return result;
}

/* 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);
  printf("%s\n", cmd);
  fflush(stdout);
  return system(cmd);
}

/* print char* in hex format */
void dump_serial_packet(const unsigned char *packet, const int len) {
    int i;
    printf("len: %d\n", len);
    if (!packet)
	return;
    for (i = 0; i < len; i++) {
	printf("%02x ", packet[i]);
	//printf("%02x(%c) ", packet[i], packet[i]);
	//printf("%c", packet[i]);
    }
    putchar('\n');
/*     printf("---\n"); */
/*     for (i = 0; i < len; i++) { */
/* 	printf("%c", packet[i]); */
/*     } */
/*     putchar('\n'); */
/*     printf("---\n"); */
}

/* ------------------------------------------------------------------------- */
/* ip6_addr_t and hw_addr_t utility functions */
int ipv6_addr_is_zero(const ip6_addr_t *addr)
{
    int i;
    for (i=0;i<16;i++) {
	if (addr->addr[i]) {
	    return 0;
	}
    }
    return 1;
}

int ipv6_addr_is_linklocal_unicast(const ip6_addr_t *addr)
{
    if (   addr->addr[0] == 0xFE
	   && addr->addr[1] == 0x80
	   && addr->addr[2] == 0
	   && addr->addr[3] == 0
	   && addr->addr[4] == 0
	   && addr->addr[5] == 0
	   && addr->addr[6] == 0
	   && addr->addr[7] == 0
	   )
	return 1;
    else
	return 0;
}

int cmp_ipv6_addr(const ip6_addr_t *addr1, const ip6_addr_t *addr2)
{
    return memcmp(addr1, addr2, sizeof(ip6_addr_t));
}

int cmp_hw_addr(const hw_addr_t *addr1, const hw_addr_t *addr2)
{
    // for short addresses compare only the first two bytes
    if (addr1->type == HW_ADDR_SHORT && addr2->type == HW_ADDR_SHORT) {
	return memcmp(addr1->addr_short, addr2->addr_short,
		      sizeof(addr1->addr_short));
    } else {
	return memcmp(addr1, addr2, sizeof(hw_addr_t));
    }
}

int hw_addr_is_broadcat(const hw_addr_t *hw_addr)
{
    if (hw_addr->type == HW_ADDR_SHORT
	&& hw_addr->addr_short[0] == 0xFF  && hw_addr->addr_short[1] == 0xFF)
	return 1;
    // TODO: long address
    else return 0;
}

/* ------------------------------------------------------------------------- */
/* more utility functions */
void clear_pkt(lowpan_pkt_t *pkt)
{
    memset(pkt, 0, sizeof(*pkt));
    pkt->buf_begin = pkt->buf + LOWPAN_OVERHEAD;
}

void free_frag_list(frag_info_t *p)
{
    frag_info_t *q;
    while (p) {
	q = p->next;
	free(p);
	p = q;
    }
}

void free_lowpan_pkt(lowpan_pkt_t *pkt)
{
    lowpan_pkt_t *p;
    lowpan_pkt_t **q;

    if (!fragments) return;
    for(q=&fragments; *q; q=&(*q)->next) {
	if (*q == pkt) {
	    p = *q;
	    *q = p->next;
	    free_frag_list(p->frag_list);
	    free(p);
	    return;
	}
    }
}

lowpan_pkt_t * find_fragment(hw_addr_t *hw_src_addr, hw_addr_t *hw_dst_addr,
			     uint16_t dgram_size, uint16_t dgram_tag)
{
    lowpan_pkt_t *p;
    for(p=fragments; p; p=p->next) {
	if ((p->dgram_tag == dgram_tag)
	    && (p->dgram_size == dgram_size)
	    && cmp_hw_addr(&p->hw_src_addr, hw_src_addr) == 0
	    && cmp_hw_addr(&p->hw_dst_addr, hw_dst_addr) == 0
	    ) {
	    return p;
	}
    }
    return NULL;
}
/* ------------------------------------------------------------------------- */
/* HC1 and HC2 compression and decompresstion functions */

/* the caller has to free() new_buf */
int lowpan_decompress(uint8_t *buf, int len,
		       const hw_addr_t *hw_src_addr,
		       const hw_addr_t *hw_dst_addr,
		       uint8_t **new_buf, int *new_len)
{
    uint8_t hc1_enc;
    uint8_t hc2_enc;
    struct ip6_hdr *ip_hdr = NULL;
    struct udp_hdr *udp_hdr = NULL;
    
    *new_buf = malloc(len + sizeof(*ip_hdr) + sizeof(*udp_hdr));
    if (!*new_buf) {
	fprintf(stderr, "%s: out of memory\n", __func__);
	*new_len = 0;
	return 1;
    }
    hc1_enc = *buf;
    buf += sizeof(hc1_enc);
    len -= sizeof(hc1_enc);

    /* HC2 encoding follows HC1 encoding */
    if ((hc1_enc & HC1_HC2_MASK) == HC1_HC2_PRESENT) {
	hc2_enc = *buf;
	buf += sizeof(hc2_enc);
	len -= sizeof(hc2_enc);
    }

    /* IP header fields */
    ip_hdr = (struct ip6_hdr *) *new_buf;
    memset(ip_hdr, 0, sizeof(struct ip6_hdr));

    ip_hdr->vtc |= IPV6_VERSION;

    ip_hdr->hlim = *buf;
    buf += sizeof(ip_hdr->hlim);
    len -= sizeof(ip_hdr->hlim);

    /* source IP address */
    if ((hc1_enc & HC1_SRC_PREFIX_MASK) == HC1_SRC_PREFIX_INLINE) {
	memcpy(&ip_hdr->src_addr, buf, sizeof(ip_hdr->src_addr)/2);
	buf += sizeof(ip_hdr->src_addr)/2;
	len -= sizeof(ip_hdr->src_addr)/2;
    } else {
	ip_hdr->src_addr.addr[0] = 0xFE;
	ip_hdr->src_addr.addr[1] = 0x80;
    }
     
    if ((hc1_enc & HC1_SRC_IFACEID_MASK) == HC1_SRC_IFACEID_INLINE) {
	memcpy(((void*)&ip_hdr->src_addr) + sizeof(ip_hdr->src_addr)/2,
	       buf, sizeof(ip_hdr->src_addr)/2);
	buf += sizeof(ip_hdr->src_addr)/2;
	len -= sizeof(ip_hdr->src_addr)/2;
    }

    /* destination IP address */
    if ((hc1_enc & HC1_DST_PREFIX_MASK) == HC1_DST_PREFIX_INLINE) {
	memcpy(&ip_hdr->dst_addr, buf, sizeof(ip_hdr->dst_addr)/2);
	buf += sizeof(ip_hdr->dst_addr)/2;
	len -= sizeof(ip_hdr->dst_addr)/2;
    } else {
	ip_hdr->dst_addr.addr[0] = 0xFE;
	ip_hdr->dst_addr.addr[1] = 0x80;
    }
     
    if ((hc1_enc & HC1_DST_IFACEID_MASK) == HC1_DST_IFACEID_INLINE) {
	memcpy(((void*)&ip_hdr->dst_addr) + sizeof(ip_hdr->dst_addr)/2,
	       buf, sizeof(ip_hdr->dst_addr)/2);
	buf += sizeof(ip_hdr->dst_addr)/2;
	len -= sizeof(ip_hdr->dst_addr)/2;
    }

    /* Traffic Class and Flow Label */
    if ((hc1_enc & HC1_TCFL_MASK) == HC1_TCFL_INLINE) {
	//TODO
    }

    /* Next Header */
    switch (hc1_enc & HC1_NEXTHDR_MASK) {
    case HC1_NEXTHDR_INLINE:
	ip_hdr->nxt_hdr = *buf;
	buf += sizeof(ip_hdr->nxt_hdr);
	len -= sizeof(ip_hdr->nxt_hdr);
	break;
    case HC1_NEXTHDR_UDP:
	ip_hdr->nxt_hdr = NEXT_HEADER_UDP;
	break;
    case HC1_NEXTHDR_ICMP:
	ip_hdr->nxt_hdr = NEXT_HEADER_ICMP6;
	break;
    case HC1_NEXTHDR_TCP:
	ip_hdr->nxt_hdr = NEXT_HEADER_TCP;
	break;
    default:
	fprintf(stderr, "unknown next header HC1 encoding\n");
	break;
    }
    
    /* HC_UDP compression */
    if ((hc1_enc & HC1_HC2_MASK) == HC1_HC2_PRESENT
	&& (hc1_enc & HC1_NEXTHDR_MASK) == HC1_NEXTHDR_UDP) {
	
	udp_hdr = (struct udp_hdr *) ((*new_buf) + sizeof(struct ip6_hdr));
	//udp_hdr = (struct udp_hdr *) (ip_hdr + 1);
	memset(udp_hdr, 0, sizeof(struct udp_hdr));

	/* UDP Source Port */
	if ((hc2_enc & HC2_UDP_SRC_PORT_MASK) == HC2_UDP_SRC_PORT_INLINE) {
	    memcpy(&udp_hdr->src_port, buf, sizeof(udp_hdr->src_port));
	    buf += sizeof(udp_hdr->src_port);
	    len -= sizeof(udp_hdr->src_port);
	} else {
	    //TODO
	}

	/* UDP Destination Port */
	if ((hc2_enc & HC2_UDP_DST_PORT_MASK) == HC2_UDP_DST_PORT_INLINE) {
	    memcpy(&udp_hdr->dst_port, buf, sizeof(udp_hdr->dst_port));
	    buf += sizeof(udp_hdr->dst_port);
	    len -= sizeof(udp_hdr->dst_port);
	} else {
	    //TODO
	}

	/* UDP Length */
	if ((hc2_enc & HC2_UDP_LEN_MASK) == HC2_UDP_LEN_INLINE) {
	    memcpy(&udp_hdr->len, buf, sizeof(udp_hdr->len));
	    buf += sizeof(udp_hdr->len);
	    len -= sizeof(udp_hdr->len);
	} else {
	    udp_hdr->len = len - sizeof(udp_hdr->chksum)
		+ sizeof(struct udp_hdr);
	}
	
	/* Checksum */
	memcpy(&udp_hdr->chksum, buf, sizeof(udp_hdr->chksum));
	buf += sizeof(udp_hdr->chksum);
	len -= sizeof(udp_hdr->chksum);
	
	/* IPv6 Payload Length */
	ip_hdr->plen = htons(len + sizeof(struct udp_hdr));
	
	memcpy((*new_buf) + sizeof(struct ip6_hdr) + sizeof(struct udp_hdr),

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -