📄 serial_tun.c
字号:
buf, len); *new_len = len + sizeof(struct ip6_hdr) + sizeof(struct udp_hdr); } else { /* IPv6 Payload Length */ ip_hdr->plen = htons(len); memcpy((*new_buf) + sizeof(struct ip6_hdr), buf, len); *new_len = len + sizeof(struct ip6_hdr); } return 0;}/* assuming there is space available in from of buf_begin */int lowpan_compress(uint8_t **buf_begin, int *len, const hw_addr_t *hw_src_addr, const hw_addr_t *hw_dst_addr){ uint8_t *hc1_enc; uint8_t *hc2_enc; struct ip6_hdr *ip_hdr = NULL; struct udp_hdr *udp_hdr = NULL; uint8_t new_buf[sizeof(struct ip6_hdr) + sizeof(struct udp_hdr) + 5]; uint8_t *new_buf_p = new_buf; int new_len = 0; debug("%s\n", __func__); ip_hdr = (struct ip6_hdr *) *buf_begin; udp_hdr = (struct udp_hdr *) ((*buf_begin) + sizeof(struct ip6_hdr)); /* check if this is an IPv6 packet */ if ((ip_hdr->vtc & IPV6_VERSION_MASK) != IPV6_VERSION) { debug("IP version check failed - not an IPv6 packet\n"); return 0; } /* set 6lowpan dispatch value */ *new_buf_p = DISPATCH_COMPRESSED_IPV6; new_buf_p += sizeof(uint8_t); new_len += sizeof(uint8_t); /* HC1 encoding field */ hc1_enc = new_buf_p; new_buf_p += sizeof(uint8_t); new_len += sizeof(uint8_t); *hc1_enc = 0; /* does HC2 follow after HC1? */ if (ip_hdr->nxt_hdr == NEXT_HEADER_UDP) { *hc1_enc |= HC1_HC2_PRESENT; /* HC2 encoding field */ hc2_enc = new_buf_p; new_buf_p += sizeof(uint8_t); new_len += sizeof(uint8_t); *hc2_enc = 0; } else { *hc1_enc |= HC1_HC2_NONE; } /* Hop Limit */ *new_buf_p = ip_hdr->hlim; new_buf_p += sizeof(uint8_t); new_len += sizeof(uint8_t); /* source address prefix */ //TODO: fails checksum on the mote !!! if (ipv6_addr_is_linklocal_unicast(&ip_hdr->src_addr)) { *hc1_enc |= HC1_SRC_PREFIX_LINKLOCAL; } else { *hc1_enc |= HC1_SRC_PREFIX_INLINE; memcpy(new_buf_p, &(ip_hdr->src_addr), 8); new_buf_p += 8; new_len += 8; } /* source address interface identifier */ *hc1_enc |= HC1_SRC_IFACEID_INLINE; memcpy(new_buf_p, ((void*)&(ip_hdr->src_addr)) + 8, 8); new_buf_p += 8; new_len += 8; /* destination address prefix */ if (ipv6_addr_is_linklocal_unicast(&ip_hdr->dst_addr)) { *hc1_enc |= HC1_DST_PREFIX_LINKLOCAL; } else { *hc1_enc |= HC1_DST_PREFIX_INLINE; memcpy(new_buf_p, &(ip_hdr->dst_addr), 8); new_buf_p += 8; new_len += 8; } /* destination address interface identifier */ *hc1_enc |= HC1_DST_IFACEID_INLINE; memcpy(new_buf_p, ((void*)&(ip_hdr->dst_addr)) + 8, 8); new_buf_p += 8; new_len += 8; /* we're always sending packets with TC anf FL zero */ *hc1_enc |= HC1_TCFL_ZERO; /* next header */ switch (ip_hdr->nxt_hdr) { case NEXT_HEADER_UDP: *hc1_enc |= HC1_NEXTHDR_UDP; break; case NEXT_HEADER_ICMP6: *hc1_enc |= HC1_NEXTHDR_ICMP; break; case NEXT_HEADER_TCP: *hc1_enc |= HC1_NEXTHDR_TCP; break; default: *hc1_enc |= HC1_NEXTHDR_INLINE; *new_buf_p = ip_hdr->nxt_hdr; new_buf_p += sizeof(ip_hdr->nxt_hdr); new_len += sizeof(ip_hdr->nxt_hdr); break; } /* HC_UDP encoding */ if ((*hc1_enc & HC1_HC2_MASK) == HC1_HC2_PRESENT && (*hc1_enc & HC1_NEXTHDR_MASK) == HC1_NEXTHDR_UDP) { /* Source Port */ *hc2_enc |= HC2_UDP_SRC_PORT_INLINE; memcpy(new_buf_p, &udp_hdr->src_port, sizeof(udp_hdr->src_port)); new_buf_p += sizeof(udp_hdr->src_port); new_len += sizeof(udp_hdr->src_port); /* Destination Port */ *hc2_enc |= HC2_UDP_DST_PORT_INLINE; memcpy(new_buf_p, &udp_hdr->dst_port, sizeof(udp_hdr->dst_port)); new_buf_p += sizeof(udp_hdr->dst_port); new_len += sizeof(udp_hdr->dst_port); /* Length */ //*hc2_enc |= HC2_UDP_LEN_COMPR; *hc2_enc |= HC2_UDP_LEN_INLINE; memcpy(new_buf_p, &udp_hdr->len, sizeof(udp_hdr->len)); new_buf_p += sizeof(udp_hdr->len); new_len += sizeof(udp_hdr->len); /* Checksum */ memcpy(new_buf_p, &udp_hdr->chksum, sizeof(udp_hdr->chksum)); new_buf_p += sizeof(udp_hdr->chksum); new_len += sizeof(udp_hdr->chksum); /* replace the IP and UDP headers with the compressed ones */ *len += new_len; *len -= sizeof(struct ip6_hdr); *len -= sizeof(struct udp_hdr); *buf_begin += sizeof(struct ip6_hdr); *buf_begin += sizeof(struct udp_hdr); *buf_begin -= new_len; memcpy(*buf_begin, new_buf, new_len); } else { /* replace the IP header with the compressed one */ *len += new_len; *len -= sizeof(struct ip6_hdr); *buf_begin += sizeof(struct ip6_hdr); *buf_begin -= new_len; memcpy(*buf_begin, new_buf, new_len); } return 0;}/* ------------------------------------------------------------------------- *//* handling of data arriving on the tun interface *//* * encapsulate buf as an Active Message payload * fragments packets if needed */int serial_output_am_payload(uint8_t *buf, int len, const hw_addr_t *hw_src_addr, const hw_addr_t *hw_dst_addr){ am_packet_t AMpacket; int result; //debug("%s: dumping buf (len: %d)...\n", __func__, len); //dump_serial_packet(buf, len); if (len > LINK_DATA_MTU) { fprintf(stderr, "%s: requested to send more than LINK_DATA_MTU"\ "(%d bytes)\n", __func__, len); // TODO: maybe we should send the fisr LINK_DATA_MTU bytes // and only print a warning return -1; } memset(&AMpacket, 0, sizeof(AMpacket)); AMpacket.pkt_type = 0; // TODO: make the dst addr handling more general //AMpacket.dst = htons(0x14); AMpacket.dst = htons(0xFFFF); //AMpacket.src = htons(0x12); // TODO: make the src addr handling more general memcpy(&AMpacket.src, hw_addr.addr_short, 2); AMpacket.group = 0; AMpacket.type = 0x41; AMpacket.length = min(len,LINK_DATA_MTU); //AMpacket.data = buf; memcpy(AMpacket.data, buf, AMpacket.length); len = AMpacket.length + 8; // data + header debug("sending to serial port...\n"); dump_serial_packet((unsigned char *)&AMpacket, len); result = write_serial_packet(ser_src, &AMpacket, len); /* * Returns: 0 if packet successfully written, 1 if successfully * written but not acknowledged, -1 otherwise */ debug("write_serial_packet returned %d\n", result); if (result < 0) { perror ("sendto"); return -1; } return len;}/* * read data from the tun device and send it to the serial port * does also fragmentation */int tun_input(){ uint8_t buf[LOWPAN_MTU + LOWPAN_OVERHEAD]; uint8_t *buf_begin = buf + LOWPAN_OVERHEAD; int len; int result; struct lowpan_frag_hdr *frag_hdr; uint8_t dgram_offset = 0; uint16_t dgram_size; hw_addr_t hw_dst_addr; uint8_t frag_len; /* length of the fragment just being sent */ uint8_t *frame_begin; /* begin of the frame payload */ uint8_t frame_len; /* length of the frame payload */ len = tun_read (tun_fd, (char*) buf_begin, LOWPAN_MTU); if (len <= 0) { perror ("read"); return 0; } printf("data on tun interface\n"); /* set 802.15.4 destination address */ hw_dst_addr.type = HW_ADDR_SHORT; hw_dst_addr.addr_short[0] =0xFF; hw_dst_addr.addr_short[1] =0xFF; /* HC compression */ lowpan_compress(&buf_begin, &len, &hw_addr, &hw_dst_addr); /* prepend dispatch *//* buf_begin--; *//* *buf_begin = DISPATCH_UNCOMPRESSED_IPV6; *//* len++; */ /* determine if fragmentation is needed */ if (len > LINK_DATA_MTU) { /* fragmentation needed */ increment_g_dgram_tag(); dgram_size = htons(len); /* first fragment */ debug("first fragment... (len: %d, offset: %d)\n", len, dgram_offset); /* fragment heder */ frame_begin = buf_begin - sizeof(struct lowpan_frag_hdr); frag_hdr = (struct lowpan_frag_hdr *) frame_begin; frag_hdr->dgram_size = dgram_size; frag_hdr->dispatch |= DISPATCH_FIRST_FRAG; frag_hdr->dgram_tag = g_dgram_tag; /* align fragment length at an 8-byte multiple */ frag_len = LINK_DATA_MTU - sizeof(struct lowpan_frag_hdr); frag_len -= frag_len%8; frame_len = frag_len + sizeof(struct lowpan_frag_hdr); result = serial_output_am_payload(frame_begin, frame_len, &hw_addr, &hw_dst_addr); if (result < 0) { perror("serial_output_am_payload() failed\n"); return -1; } buf_begin += frag_len; len -= frag_len; dgram_offset += frag_len/8; /* in 8-byte multiples */ /* subseq fragment */ while (len > 0) { usleep(10000); /* workaround to prevent loosing fragments */ debug("subsequent fragment... (len: %d, offset: %d)\n", len, dgram_offset); /* dgram_offset */ frame_begin = buf_begin - sizeof(uint8_t); *(frame_begin) = dgram_offset; /* fragment heder */ frame_begin -= sizeof(struct lowpan_frag_hdr); frag_hdr = (struct lowpan_frag_hdr *) frame_begin; frag_hdr->dgram_size = dgram_size; frag_hdr->dispatch |= DISPATCH_SUBSEQ_FRAG; frag_hdr->dgram_tag = g_dgram_tag; if (len <= LINK_DATA_MTU - sizeof(struct lowpan_frag_hdr) - sizeof(uint8_t)) { /* * last fragment does not have to be aligned * at an 8-byte multiple */ frag_len = len; } else { /* align fragment length at an 8-byte multiple */ frag_len = LINK_DATA_MTU - sizeof(struct lowpan_frag_hdr) - sizeof(uint8_t); frag_len -= frag_len%8; } frame_len = frag_len + sizeof(struct lowpan_frag_hdr) + sizeof(uint8_t); result = serial_output_am_payload(frame_begin, frame_len, &hw_addr, &hw_dst_addr); if (result < 0) { perror("serial_output_am_payload() failed\n"); //return -1; } buf_begin += frag_len; len -= frag_len; dgram_offset += frag_len/8; /* in 8-byte multiples */ } return 1; } else { /* no need for fragmentation */ serial_output_am_payload(buf_begin, len, &hw_addr, &hw_dst_addr); return 1; }}/* ------------------------------------------------------------------------- *//* handling of data arriving on the serial port *//* * read data on serial port and send it to the tun interface * does fragment reassembly */int serial_input(){ int result = 0; void *ser_data; /* data read from serial port */ int ser_len; /* length of data read from serial port */ uint8_t *buf; int len; am_packet_t *AMpacket; struct hw_addr hw_src_addr; struct hw_addr hw_dst_addr; uint8_t *dispatch; struct lowpan_broadcast_hdr *bc_hdr; struct lowpan_frag_hdr *frag_hdr; uint16_t dgram_tag; uint16_t dgram_size; uint8_t dgram_offset; struct timeval tv; frag_info_t *p; frag_info_t **q; int last_frag; lowpan_pkt_t *pkt; printf("serial_input()\n"); /* read data from serial port */ ser_data = read_serial_packet(ser_src, &ser_len); /* process the packet we have received */ if (ser_len && ser_data) { printf("dumping data on serial port...\n"); dump_serial_packet(ser_data, ser_len); AMpacket = ser_data; /* copy 802.15.4 addresses */ // TODO: check if I got the byte ordering right hw_src_addr.type = HW_ADDR_SHORT; memcpy(hw_src_addr.addr_short, &AMpacket->src, sizeof(hw_src_addr.addr_short)); hw_dst_addr.type = HW_ADDR_SHORT; memcpy(hw_dst_addr.addr_short, &AMpacket->dst, sizeof(hw_dst_addr.addr_short)); /* --- 6lowpan optional headers --- */ buf = AMpacket->data; len = AMpacket->length; if (len != ser_len - 8) { fprintf(stderr, "warning: mismatch between AMpacket->length(%d)"\ " and ser_len - 8(%d)", AMpacket->length, ser_len - 8); } // TODO: check if length has a sensible value dispatch = AMpacket->data; /* Mesh Addressing header */ if ( (*dispatch & DISPATCH_MESH_MASK) == DISPATCH_MESH) { /* move over the dispatch field */ buf += sizeof(*dispatch);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -