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

📄 serial_tun.c

📁 tinyos-2.x.rar
💻 C
📖 第 1 页 / 共 3 页
字号:
	    len -= sizeof(*dispatch);

	    /* Hops Left */
	    if ((*dispatch & 0x0F) == 0) {
	      goto discard_packet;
	    }
	    
	    /* Final Destination Address */
	    if (*dispatch & DISPATCH_MESH_F_FLAG) {
		hw_dst_addr.type = HW_ADDR_LONG;
		memcpy(&hw_dst_addr.addr_long, buf,
		       sizeof(hw_dst_addr.addr_long));
		buf += sizeof(hw_dst_addr.addr_long);
		len -= sizeof(hw_dst_addr.addr_long);
	    } else {
		hw_dst_addr.type = HW_ADDR_SHORT;
		memcpy(&hw_dst_addr.addr_short, buf,
		       sizeof(hw_dst_addr.addr_short));
		buf += sizeof(hw_dst_addr.addr_short);
		len -= sizeof(hw_dst_addr.addr_short);
	    }
	    
	    /* check if we're the recipient */
	    if (cmp_hw_addr(&hw_dst_addr, &hw_addr) != 0
		&& !hw_addr_is_broadcat(&hw_dst_addr)) {
		// TODO: if mesh forwarding enabled, then forward
		goto discard_packet;
	    }
	    
	    /* Originator Address */
	    if (*dispatch & DISPATCH_MESH_O_FLAG) {
		hw_src_addr.type = HW_ADDR_LONG;
		memcpy(&hw_src_addr.addr_long, buf,
		       sizeof(hw_src_addr.addr_long));
		buf += sizeof(hw_src_addr.addr_long);
		len -= sizeof(hw_src_addr.addr_long);
	    } else {
		hw_src_addr.type = HW_ADDR_SHORT;
		memcpy(&hw_src_addr.addr_short, buf,
		       sizeof(hw_src_addr.addr_short));
		buf += sizeof(hw_src_addr.addr_short);
		len -= sizeof(hw_src_addr.addr_short);
	    }
	    
	    dispatch = buf;
	}
	/* Broadcast header */
	if (*dispatch == DISPATCH_BC0) {
	    bc_hdr = (struct lowpan_broadcast_hdr *) buf;
	    // do something usefull with bc_hdr->seq_no...
	    
	    buf += (sizeof(struct lowpan_broadcast_hdr));
	    len -= (sizeof(struct lowpan_broadcast_hdr));
	    dispatch = buf;
	}

	/* fragment header */
	if ((*dispatch & DISPATCH_FRAG_MASK)
	    == DISPATCH_FIRST_FRAG
	    || (*dispatch & DISPATCH_FRAG_MASK)
	    == DISPATCH_SUBSEQ_FRAG
	    ) {
	    frag_hdr = (struct lowpan_frag_hdr *) buf;
	    buf += sizeof(struct lowpan_frag_hdr);
	    len -= sizeof(struct lowpan_frag_hdr);

	    /* collect information about the fragment */
	    dgram_tag = frag_hdr->dgram_tag;
	    dgram_size = frag_hdr->dgram_size & htons(0x07FF);
	    //dgram_size = frag_hdr->dgram_size8[1];
	    //dgram_size += ((uint16_t) (frag_hdr->dgram_size8[0] & 0x07)) << 8;
	    if ((*dispatch & DISPATCH_FRAG_MASK) == DISPATCH_SUBSEQ_FRAG) {
		dgram_offset = *buf;
		buf += 1;
		len -= 1;
	    } else {
		dgram_offset = 0;
	    }
	    
	    debug("fragment reassembly: tag: 0x%04X, size: %d, offset: %d"\
		  "(*8=%d)\n",
		  ntohs(dgram_tag), ntohs(dgram_size),
		  dgram_offset, dgram_offset*8);

	    pkt = find_fragment(&hw_src_addr, &hw_dst_addr,
				dgram_size, dgram_tag);
	    if (pkt) {
		debug("found an existing reassembly buffer\n");
		/* fragment reassembly buffer found */
		/* check for overlap */
		for (p = pkt->frag_list; p; p=p->next) {
		    if (dgram_offset == p->offset && len == p->len) {
			/* duplicate - discard it */
			result = 0;
			goto discard_packet;
		    } else if ((dgram_offset == p->offset && len < p->len) ||
			       (dgram_offset > p->offset
				&& dgram_offset < p->offset + p->len/8)
			       ) {
			goto frag_overlap;
		    }
		}
		/* no overlap found */
		goto frag_reassemble;
	    } else {
		debug("starting a new reassembly buffer\n");
		/* fragment reassembly buffer not found - set up a new one */
		pkt = malloc(sizeof(lowpan_pkt_t));
		if (!pkt) {
		    // no free slot for reassembling fragments
		    fprintf(stderr, "out of memory - dropping a fragment\n");
		    result = -1;
		    goto discard_packet;
		}
		pkt->next = fragments;
		fragments = pkt;
		clear_pkt(pkt);
		memcpy(&pkt->hw_src_addr, &hw_src_addr, sizeof(hw_src_addr));
		memcpy(&pkt->hw_dst_addr, &hw_dst_addr, sizeof(hw_dst_addr));
		pkt->dgram_tag = dgram_tag;
		pkt->dgram_size = dgram_size;
		gettimeofday(&tv, NULL);
		pkt->frag_timeout = tv.tv_sec + FRAG_TIMEOUT;
		goto frag_reassemble;
	    }
	    
	frag_overlap:
	    /* overlap - discard previous frags
	     * and restart freagment reassembly
	     */
	    free_frag_list(pkt->frag_list);
	    pkt->frag_list = NULL;
	    /* not sure if we want to clear the whole buf */
	    //memset(&pkt->buf, 0, sizeof(pkt->buf));
	    gettimeofday(&tv, NULL);
	    pkt->frag_timeout = tv.tv_sec + FRAG_TIMEOUT;
	    goto frag_reassemble;
	    
	frag_reassemble:
	    /* copy buf data */
	    debug("dgram_offset: %d\n", dgram_offset);
	    memcpy(pkt->buf_begin + dgram_offset*8, buf, len);
	    //TODO: make sure a large len does not cause a buffer overflow

	    /* update frag_info */
	    p = malloc(sizeof(frag_info_t));
	    if (!p) {
		fprintf(stderr, "out of memory - fragment "\
			"reassembly failing\n");
	    } else {
		p->offset = dgram_offset;
		p->len = len;

		/* insert frag_info into the orderer list */
		if (pkt->frag_list) {
		    for(q = &(pkt->frag_list); (*q)->next; q=&((*q)->next)) {
			if (p->offset > (*q)->offset) {
			    break;
			}
		    }
		    if ((*q)) {
			debug("inserting frag_info before offset %d\n",
			      (*q)->offset);
		    } else {
			debug("inserting frag_info at the beginning/end\n");
		    }

		    p->next = *q;
		    *q = p;
		} else {
		    debug("inserting frag_info to the beginning "
			  "of the list\n");
		    p->next = pkt->frag_list;
		    pkt->frag_list = p;
		}
	    }

	    /* check if this is not the last fragment */
	    if (!dgram_offset) {
		/* the first fragment cannot be the last one */
		last_frag = 0;
	    } else {
		debug("checking last_frag...\n");
		last_frag=1;
		dgram_offset = ntohs(dgram_size)/8;
		for(p=pkt->frag_list; p && dgram_offset; p=p->next) {
		    debug("dgram_offset: %d, p->offset: %d, p->len: %d\n",
			  dgram_offset, p->offset, p->len);
		    if (p->offset + p->len/8 != dgram_offset) {
			debug("offset mismatch - not the last fragment\n");
			last_frag = 0;
			break;
		    }
		    dgram_offset = p->offset;
		}
	    }

	    if (last_frag) {
		debug("last fragment, reassembly done\n");
		pkt->len = ntohs(dgram_size);
		
		debug("dumping reassembled datagram...\n");
		dump_serial_packet(pkt->buf_begin, pkt->len);
		
		/* pass up the complete packet */
		result = serial_input_layer3(pkt->buf_begin, pkt->len,
					     &hw_src_addr, &hw_dst_addr);
		/* deallocate pkt and all fragment info */
		free_lowpan_pkt(pkt);
	    } else {
		result = 0;
	    }
	} else { /* no fragment header present */
	    result =  serial_input_layer3(buf, len,
					  &hw_src_addr, &hw_dst_addr);
	}
	
    } else {
	//printf("no data on serial port, but FD trigerred select\n");
    }
 discard_packet:
    if (ser_data) {
	free(ser_data);
    }
    if (ser_data && ser_len > 0) {
	return 1;
    } else {
	return 0;
    }
    //return result;
}

int serial_input_layer3(uint8_t *buf, int len,
			const hw_addr_t *hw_src_addr,
			const hw_addr_t *hw_dst_addr)
{
    uint8_t *dispatch = buf;
    //debug("%s()\n", __func__);
    //dump_serial_packet(buf, len);

    if (len <= 0) return 1;

    /* uncompressed IPv6 */
    if (*dispatch == 0x41) {
	return serial_input_ipv6_uncompressed(buf+1, len-1,
					      hw_src_addr, hw_dst_addr);

    }
    /* LOWPAN_HC1 compressed IPv6 */
    else if (*dispatch == 0x42) {
	return serial_input_ipv6_compressed(buf+1, len-1,
					    hw_src_addr, hw_dst_addr);
    }
    /* unknown dispatch value if we got here */
    else {
	debug("unknown dispatch value: %X\n", *dispatch);
	return tun_write(tun_fd, (char*) buf+1, len-1);
    }
}

int serial_input_ipv6_uncompressed(uint8_t *buf, int len,
				   const hw_addr_t *hw_src_addr,
				   const hw_addr_t *hw_dst_addr)
{
    debug("%s()\n", __func__);
    //dump_serial_packet(buf, len);
    // TODO: update neighbor table
    return tun_write(tun_fd, (char*) buf, len);
}

int serial_input_ipv6_compressed(uint8_t *buf, int len,
				 const hw_addr_t *hw_src_addr,
				 const hw_addr_t *hw_dst_addr)
{
    int ret=0;
    int new_len;
    uint8_t *new_buf;

    debug("%s()\n", __func__);
    if (0 == lowpan_decompress(buf, len,
			       hw_src_addr, hw_dst_addr,
			       &new_buf, &new_len)
	) {
	// TODO: update neighbor table
	buf = new_buf;
	len = new_len;
	ret =  tun_write(tun_fd, (char*) buf, len);
	
	if (new_buf && new_len) {
	    free(new_buf);
	}
    }
    
    return ret;
}

/* ------------------------------------------------------------------------- */

void timer_fired()
{
    struct timeval tv;
    lowpan_pkt_t *p;
    lowpan_pkt_t **q;

    /* time out old fragments */
    (void) gettimeofday(&tv, NULL);
    for(q = &fragments; *q; ) {
	if ((*q)->frag_timeout > tv.tv_sec) {
	    p = (*q)->next;
	    free(*q);
	    *q = p;
	} else {
	    q = &((*q)->next);
	}
    }
    // TODO: ND retransmission
    // TODO: neighbor table timeouts
}

/* shifts data between the serial port and the tun interface */
int serial_tunnel(serial_source ser_src, int tun_fd) {
    //int result;
    fd_set fs;
    
    while (1) {
	FD_ZERO (&fs);
	FD_SET (tun_fd, &fs);
	FD_SET (serial_source_fd(ser_src), &fs);

	select (tun_fd>serial_source_fd(ser_src)?
		tun_fd+1 : serial_source_fd(ser_src)+1,
		&fs, NULL, NULL, NULL);

	debug("--- select() fired ---\n");

	/* data available on tunnel device */
	if (FD_ISSET (tun_fd, &fs)) {
	    //result = tun_input();
	    while( tun_input() );
	}
	
	/* data available on serial port */
	if (FD_ISSET (serial_source_fd(ser_src), &fs)) {
	    /* more packets may be queued so process them all */
	    while (serial_input());
	    /* using serial_source_empty() seems to make select()
	     * fire way too often, so the above solution is better */
	    //while(! serial_source_empty(ser_src)) {
	    //result = serial_input();
		//}
	}
	/* end of data available */
    }
    /* end of while(1) */
    
    return 0;
}

int main(int argc, char **argv) {
    char dev[16];
    
    if (argc != 3)
	{
	    fprintf(stderr, "Usage: %s <device> <rate>\n", argv[0]);
	    exit(2);
	}
    
    hw_addr.type = HW_ADDR_SHORT;
    hw_addr.addr_short[0] = 0x00; // network byte order
    hw_addr.addr_short[1] = 0x12;

    /* create the tunnel device */
    dev[0] = 0;
    tun_fd = tun_open(dev);
    if (tun_fd < 1) {
	printf("Could not create tunnel device. Fatal.\n");
		return 1;
    }
    else {
	printf("Created tunnel device: %s\n", dev);
    }
    
    /* open the serial port */
    ser_src = open_serial_source(argv[1], platform_baud_rate(argv[2]),
				 1, stderr_msg);
    /* 0 - blocking reads
     * 1 - non-blocking reads
     */
    
    if (!ser_src) {
	debug("Couldn't open serial port at %s:%s\n",
		argv[1], argv[2]);
	exit(1);
    }
    
    /* set up the tun interface */
    printf("\n");
    ssystem("ifconfig tun0 up");
    ssystem("ifconfig tun0 mtu 1280");
    ssystem("ifconfig tun0 inet6 add 2001:0638:0709:1234::fffe:12/64");
    ssystem("ifconfig tun0 inet6 add fe80::fffe:12/64");
    printf("\n");

    printf("try:\n\tsudo ping6 -s 0 2001:0638:0709:1234::fffe:14\n"
	   "\tnc6 -u 2001:0638:0709:1234::fffe:14 1234\n\n");

    /* start tunneling */
    serial_tunnel(ser_src, tun_fd);
    
    /* clean up */
    close_serial_source(ser_src);
    //close(ser_fd);
    tun_close(tun_fd, dev);
    return 0;
}

⌨️ 快捷键说明

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