예제 #1
0
static int netdev_send(struct vport *vport, struct sk_buff *skb)
{
	struct netdev_vport *netdev_vport = netdev_vport_priv(vport);
	int mtu = netdev_vport->dev->mtu;
	int len;

	if (unlikely(packet_length(skb) > mtu && !skb_is_gso(skb))) {
		net_warn_ratelimited("%s: dropped over-mtu packet: %d > %d\n",
				     ovs_dp_name(vport->dp),
				     packet_length(skb), mtu);
		goto error;
	}

	if (unlikely(skb_warn_if_lro(skb)))
		goto error;

	skb->dev = netdev_vport->dev;
	len = skb->len;
	dev_queue_xmit(skb);

	return len;

error:
	kfree_skb(skb);
	ovs_vport_record_error(vport, VPORT_E_TX_DROPPED);
	return 0;
}
예제 #2
0
uint16_t SNMPClass::writeHeaders(SNMP_PDU *pdu)
{
  byte i;

  // SNMP community string
  if(_dstType == SNMP_PDU_SET){
    for(i = _setSize-1; i >= 0 && i <= 30; i--){
      _packet[_packetPos--] = (byte)_setCommName[i];
    }
    _packet[_packetPos--] = (byte)_setSize;	// length
  }else if(_dstType == SNMP_PDU_TRAP || _dstType == SNMP_PDU_TRAP2 || _dstType == SNMP_PDU_INFORM_REQUEST){
    for(i = _trapSize-1; i >= 0 && i <= 30; i--){
      _packet[_packetPos--] = (byte)_trapCommName[i];
    }
    _packet[_packetPos--] = (byte)_trapSize;	// length
  }else {
    for(i = _getSize-1; i >= 0 && i <= 30; i--){
      _packet[_packetPos--] = (byte)_getCommName[i];
    }
    _packet[_packetPos--] = (byte)_getSize;	// length
  }
  _packet[_packetPos--] = (byte)SNMP_SYNTAX_OCTETS;// type
  
  // version
  _packet[_packetPos--] = (byte)pdu->version;// value
  _packet[_packetPos--] = 0x01;			// length
  _packet[_packetPos--] = (byte)SNMP_SYNTAX_INT;//type
  
  //start of header
  //length of all data after this point
  _packet[_packetPos] = lsb(packet_length()+_extra_data_size);
  _packet[_packetPos-1] = msb(packet_length()+_extra_data_size);
  _packetPos -= 2;
  _packet[_packetPos--] = 0x82;//Sending length in two octets

  _packet[_packetPos--] = (byte)SNMP_SYNTAX_SEQUENCE;
  
  //packet type
  if ( _dstType == SNMP_PDU_SET ) {
    _packetSize += _setSize;
  } else if ( _dstType == SNMP_PDU_TRAP ) {
    _packetSize += _trapSize;
  } else {
    _packetSize += _getSize;
  }

  return _packetPos;
}
예제 #3
0
int packet_read(int fd, char **src_buf, size_t *src_len,
		char *buffer, unsigned size, int options)
{
	int len, ret;
	char linelen[4];

	ret = get_packet_data(fd, src_buf, src_len, linelen, 4, options);
	if (ret < 0)
		return ret;
	len = packet_length(linelen);
	if (len < 0)
		die("protocol error: bad line length character: %.4s", linelen);
	if (!len) {
		packet_trace("0000", 4, 0);
		return 0;
	}
	len -= 4;
	if (len >= size)
		die("protocol error: bad line length %d", len);
	ret = get_packet_data(fd, src_buf, src_len, buffer, len, options);
	if (ret < 0)
		return ret;

	if ((options & PACKET_READ_CHOMP_NEWLINE) &&
	    len && buffer[len-1] == '\n')
		len--;

	buffer[len] = 0;
	packet_trace(buffer, len, 0);
	return len;
}
예제 #4
0
파일: pkt-line.c 프로젝트: julesbowden/git
int packet_get_line(struct strbuf *out,
	char **src_buf, size_t *src_len)
{
	int len;

	if (*src_len < 4)
		return -1;
	len = packet_length(*src_buf);
	if (len < 0)
		return -1;
	if (!len) {
		*src_buf += 4;
		*src_len -= 4;
		packet_trace("0000", 4, 0);
		return 0;
	}
	if (*src_len < len)
		return -2;

	*src_buf += 4;
	*src_len -= 4;
	len -= 4;

	strbuf_add(out, *src_buf, len);
	*src_buf += len;
	*src_len -= len;
	packet_trace(out->buf, out->len, 0);
	return len;
}
예제 #5
0
int sick_transaction(sick_t *s, uint8_t *request, uint8_t responsetype, uint8_t *response, int timeoutms)
{
    pthread_mutex_lock(&s->writelock);

    int res = 0;
    int trials = 0;
    int requestlen;

retry:
    requestlen = packet_length(request);

    if (s->log_packets_file) {
        for (int i = 0; i < requestlen; i++) {
            if (i%16 == 0)
                fprintf(s->log_packets_file, "TX %04x : ", i);
            fprintf(s->log_packets_file, "%02x ", request[i]);
            if ((i%16) == 15 || i+1 == requestlen)
                fprintf(s->log_packets_file, "\n");
        }
    }

    // send the request
    res = write_fully(s->serialfd, request, requestlen);

    if (res < 0) {
        printf("write failed\n");
        goto exit;
    }

    // wait for response
    s->writereqid = responsetype;
    s->writedata = response;
    s->writevalid = 0;

    struct timespec ts;
    timespec_now(&ts);
    timespec_addms(&ts, timeoutms);

    pthread_cond_timedwait(&s->writecond, &s->writelock, &ts);

    if (!s->writevalid) {
        trials++;
        if (trials > SICK_OP_MAX_RETRIES) {
            res = -2;
            goto exit;
        }
        goto retry;
    }

exit:
    s->writedata = NULL;
    s->writereqid = 0;

    pthread_mutex_unlock(&s->writelock);

    return res;
}
예제 #6
0
파일: vport.c 프로젝트: JunoZhu/ovs
void ovs_vport_send(struct vport *vport, struct sk_buff *skb)
{
	int mtu = vport->dev->mtu;

	if (unlikely(packet_length(skb) > mtu && !skb_is_gso(skb))) {
		net_warn_ratelimited("%s: dropped over-mtu packet: %d > %d\n",
				     vport->dev->name,
				     packet_length(skb), mtu);
		vport->dev->stats.tx_errors++;
		goto drop;
	}

	skb->dev = vport->dev;
	vport->ops->send(skb);
	return;

drop:
	kfree_skb(skb);
}
예제 #7
0
/* callbacks */
void stdin_cb(evutil_socket_t sock, short ev, void *arg) {
	UNUSED(ev);
	UNUSED(arg);

	static ssize_t len = 0, r = 0;

	struct proto_packet *packet = sendbuff_back(&packets);
	struct proto_header *header = &packet->header;

	TRY_SYS(r = read(sock, packet->data + len, psize - len));
	if (r) {
		len += r;
		if (len == psize) {
			/* packet is full, init */
			header_init(header, last_seqno++, len, PROTO_DATA);
			ASSERT(psize + (int) sizeof(struct proto_header) == packets.hpsize);
			ASSERT(packets.hpsize == (int) packet_length(packet));
			/* send */
			EXPECT(write(mcast_sock, packet, packets.hpsize) == packets.hpsize,
					"Sending streming data failed.");
			/* start new packet */
			len = 0;
			sendbuff_next(&packets);
		}
	} else {
		if (len) {
			/* end of input, init packet as is */
			header_init(header, last_seqno++, len, PROTO_DATA);
			/* send */
			ASSERT(len + sizeof(struct proto_header));
			len = packet_length(packet);
			EXPECT(write(mcast_sock, packet, len) == len,
					"Sending streaming data failed.");
			/* everything sent */
			len = 0;
		}
		/* end of input file, exit */
		event_base_loopexit(base, NULL);
	}
}
예제 #8
0
파일: vport.c 프로젝트: Grim-lock/ovs
void ovs_vport_send(struct vport *vport, struct sk_buff *skb, u8 mac_proto)
{
	int mtu = vport->dev->mtu;

	switch (vport->dev->type) {
	case ARPHRD_NONE:
		if (mac_proto == MAC_PROTO_ETHERNET) {
			skb_reset_network_header(skb);
			skb_reset_mac_len(skb);
			skb->protocol = htons(ETH_P_TEB);
		} else if (mac_proto != MAC_PROTO_NONE) {
			WARN_ON_ONCE(1);
			goto drop;
		}
		break;
	case ARPHRD_ETHER:
		if (mac_proto != MAC_PROTO_ETHERNET)
			goto drop;
		break;
	default:
		goto drop;
	}

	if (unlikely(packet_length(skb, vport->dev) > mtu &&
		     !skb_is_gso(skb))) {
		net_warn_ratelimited("%s: dropped over-mtu packet: %d > %d\n",
				     vport->dev->name,
				     packet_length(skb, vport->dev), mtu);
		vport->dev->stats.tx_errors++;
		goto drop;
	}

	skb->dev = vport->dev;
	vport->ops->send(skb);
	return;

drop:
	kfree_skb(skb);
}
예제 #9
0
static int netdev_send(struct vport *vport, struct sk_buff *skb)
{
	struct netdev_vport *netdev_vport = netdev_vport_priv(vport);
	int mtu = netdev_vport->dev->mtu;
	int len;

	if (unlikely(packet_length(skb) > mtu && !skb_is_gso(skb))) {
		net_warn_ratelimited("%s: dropped over-mtu packet: %d > %d\n",
				     netdev_vport->dev->name,
				     packet_length(skb), mtu);
		goto drop;
	}

	skb->dev = netdev_vport->dev;
	len = skb->len;
	dev_queue_xmit(skb);

	return len;

drop:
	kfree_skb(skb);
	return 0;
}
예제 #10
0
int vnsw_dev_queue_push_xmit(struct sk_buff *skb)
{
	/* drop mtu oversized packets except gso */
	if (packet_length(skb) > skb->dev->mtu && !skb_is_gso(skb))
		kfree_skb(skb);
	else {
		/* ip_fragment doesn't copy the MAC header */
		if (nf_bridge_maybe_copy_header(skb))
			kfree_skb(skb);
		else {
			skb_push(skb, ETH_HLEN);
			dev_queue_xmit(skb);
		}
	}

	return 0;
}
예제 #11
0
int sick_get_type(sick_t *s, char *buf, int bufmax)
{
    uint8_t payload[1], request[SICK_MAX_MSG_LENGTH], response[SICK_MAX_MSG_LENGTH];
    payload[0] = 0x3a;
    make_telegram(payload, 1, request);

    int res = sick_transaction(s, request, payload[0] | 0x80, response, SICK_OP_TIMEOUT_MS);
    if (res < 0)
        return res;

    int typelen = packet_length(response) - 10;
    if (typelen > bufmax-1)
        typelen = bufmax - 1;
    memcpy(buf, &response[5], typelen);
    buf[typelen] = 0;

    return 0;
}
예제 #12
0
파일: pkt-line.c 프로젝트: julesbowden/git
int packet_read_line(int fd, char *buffer, unsigned size)
{
	int len;
	char linelen[4];

	safe_read(fd, linelen, 4);
	len = packet_length(linelen);
	if (len < 0)
		die("protocol error: bad line length character: %.4s", linelen);
	if (!len) {
		packet_trace("0000", 4, 0);
		return 0;
	}
	len -= 4;
	if (len >= size)
		die("protocol error: bad line length %d", len);
	safe_read(fd, buffer, len);
	buffer[len] = 0;
	packet_trace(buffer, len, 0);
	return len;
}
예제 #13
0
void sick_display_telegram(unsigned char *b)
{
    if (b[0]!=0x02) {
        printf("invalid telegram\n");
        return;
    }

    if (b[4]==0x92) {
        printf("NACK/Incorrect command\n");
    }

    int packetlength = packet_length(b);

    for (int i = 0; i < packetlength; i++) {
        if ((i%16)==0)
            printf("%04X : ",i);
        printf("%02X ", b[i]);
        if ((i%16)==15)
            printf("\n");
    }
    printf("\n");
}
예제 #14
0
/* function: ipv6_packet
 * takes an ipv6 packet and hands it off to the layer 4 protocol function
 * out    - output packet
 * packet - packet data
 * len    - size of packet
 * returns: the highest position in the output clat_packet that's filled in
 */
int ipv6_packet(clat_packet out, clat_packet_index pos, const uint8_t *packet, size_t len) {
  const struct ip6_hdr *ip6 = (struct ip6_hdr *) packet;
  struct iphdr *ip_targ = (struct iphdr *) out[pos].iov_base;
  struct ip6_frag *frag_hdr = NULL;
  uint8_t protocol;
  const uint8_t *next_header;
  size_t len_left;
  uint32_t old_sum, new_sum;
  int iov_len;

  if(len < sizeof(struct ip6_hdr)) {
    logmsg_dbg(ANDROID_LOG_ERROR, "ipv6_packet/too short for an ip6 header: %d", len);
    return 0;
  }

  if(IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
    log_bad_address("ipv6_packet/multicast %s->%s", &ip6->ip6_src, &ip6->ip6_dst);
    return 0; // silently ignore
  }

  // If the packet is not from the plat subnet to the local subnet, or vice versa, drop it, unless
  // it's an ICMP packet (which can come from anywhere). We do not send IPv6 packets from the plat
  // subnet to the local subnet, but these can appear as inner packets in ICMP errors, so we need
  // to translate them. We accept third-party ICMPv6 errors, even though their source addresses
  // cannot be translated, so that things like unreachables and traceroute will work. fill_ip_header
  // takes care of faking a source address for them.
  if (!(is_in_plat_subnet(&ip6->ip6_src) &&
        IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &Global_Clatd_Config.ipv6_local_subnet)) &&
      !(is_in_plat_subnet(&ip6->ip6_dst) &&
        IN6_ARE_ADDR_EQUAL(&ip6->ip6_src, &Global_Clatd_Config.ipv6_local_subnet)) &&
      ip6->ip6_nxt != IPPROTO_ICMPV6) {
    log_bad_address("ipv6_packet/wrong source address: %s->%s", &ip6->ip6_src, &ip6->ip6_dst);
    return 0;
  }

  next_header = packet + sizeof(struct ip6_hdr);
  len_left = len - sizeof(struct ip6_hdr);

  protocol = ip6->ip6_nxt;

  /* Fill in the IPv4 header. We need to do this before we translate the packet because TCP and
   * UDP include parts of the IP header in the checksum. Set the length to zero because we don't
   * know it yet.
   */
  fill_ip_header(ip_targ, 0, protocol, ip6);
  out[pos].iov_len = sizeof(struct iphdr);

  // If there's a Fragment header, parse it and decide what the next header is.
  // Do this before calculating the pseudo-header checksum because it updates the next header value.
  if (protocol == IPPROTO_FRAGMENT) {
    frag_hdr = (struct ip6_frag *) next_header;
    if (len_left < sizeof(*frag_hdr)) {
      logmsg_dbg(ANDROID_LOG_ERROR, "ipv6_packet/too short for fragment header: %d", len);
      return 0;
    }

    next_header += sizeof(*frag_hdr);
    len_left -= sizeof(*frag_hdr);

    protocol = parse_frag_header(frag_hdr, ip_targ);
  }

  // ICMP and ICMPv6 have different protocol numbers.
  if (protocol == IPPROTO_ICMPV6) {
    protocol = IPPROTO_ICMP;
    ip_targ->protocol = IPPROTO_ICMP;
  }

  /* Calculate the pseudo-header checksum.
   * Technically, the length that is used in the pseudo-header checksum is the transport layer
   * length, which is not the same as len_left in the case of fragmented packets. But since
   * translation does not change the transport layer length, the checksum is unaffected.
   */
  old_sum = ipv6_pseudo_header_checksum(ip6, len_left, protocol);
  new_sum = ipv4_pseudo_header_checksum(ip_targ, len_left);

  // Does not support IPv6 extension headers except Fragment.
  if (frag_hdr && (frag_hdr->ip6f_offlg & IP6F_OFF_MASK)) {
    iov_len = generic_packet(out, pos + 2, next_header, len_left);
  } else if (protocol == IPPROTO_ICMP) {
    iov_len = icmp6_packet(out, pos + 2, (const struct icmp6_hdr *) next_header, len_left);
  } else if (protocol == IPPROTO_TCP) {
    iov_len = tcp_packet(out, pos + 2, (const struct tcphdr *) next_header, old_sum, new_sum,
                         len_left);
  } else if (protocol == IPPROTO_UDP) {
    iov_len = udp_packet(out, pos + 2, (const struct udphdr *) next_header, old_sum, new_sum,
                         len_left);
  } else if (protocol == IPPROTO_GRE) {
    iov_len = generic_packet(out, pos + 2, next_header, len_left);
  } else {
#if CLAT_DEBUG
    logmsg(ANDROID_LOG_ERROR, "ipv6_packet/unknown next header type: %x", ip6->ip6_nxt);
    logcat_hexdump("ipv6/nxthdr", packet, len);
#endif
    return 0;
  }

  // Set the length and calculate the checksum.
  ip_targ->tot_len = htons(ntohs(ip_targ->tot_len) + packet_length(out, pos));
  ip_targ->check = ip_checksum(ip_targ, sizeof(struct iphdr));
  return iov_len;
}
예제 #15
0
static int netdev_send(struct vport *vport, struct sk_buff *skb)
{
	struct netdev_vport *netdev_vport = netdev_vport_priv(vport);
	int mtu = netdev_vport->dev->mtu;
	int len;

	if (unlikely(packet_length(skb) > mtu && !skb_is_gso(skb))) {
		if (net_ratelimit())
			pr_warn("%s: dropped over-mtu packet: %d > %d\n",
				ovs_dp_name(vport->dp), packet_length(skb), mtu);
		goto error;
	}

	if (unlikely(skb_warn_if_lro(skb)))
		goto error;

	skb->dev = netdev_vport->dev;
	forward_ip_summed(skb, true);

	if (vlan_tx_tag_present(skb) && !dev_supports_vlan_tx(skb->dev)) {
		int features;

		features = netif_skb_features(skb);

		if (!vlan_tso)
			features &= ~(NETIF_F_TSO | NETIF_F_TSO6 |
				      NETIF_F_UFO | NETIF_F_FSO);

		if (netif_needs_gso(skb, features)) {
			struct sk_buff *nskb;

			nskb = skb_gso_segment(skb, features);
			if (!nskb) {
				if (unlikely(skb_cloned(skb) &&
				    pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) {
					kfree_skb(skb);
					return 0;
				}

				skb_shinfo(skb)->gso_type &= ~SKB_GSO_DODGY;
				goto tag;
			}

			if (IS_ERR(nskb)) {
				kfree_skb(skb);
				return 0;
			}
			consume_skb(skb);
			skb = nskb;

			len = 0;
			do {
				nskb = skb->next;
				skb->next = NULL;

				skb = __vlan_put_tag(skb, vlan_tx_tag_get(skb));
				if (likely(skb)) {
					len += skb->len;
					vlan_set_tci(skb, 0);
					dev_queue_xmit(skb);
				}

				skb = nskb;
			} while (skb);

			return len;
		}

tag:
		skb = __vlan_put_tag(skb, vlan_tx_tag_get(skb));
		if (unlikely(!skb))
			return 0;
		vlan_set_tci(skb, 0);
	}

	len = skb->len;
	dev_queue_xmit(skb);

	return len;

error:
	kfree_skb(skb);
	ovs_vport_record_error(vport, VPORT_E_TX_DROPPED);
	return 0;
}
예제 #16
0
uint32_t SNMPClass::send_message(SNMP_PDU *pdu, IPAddress to_address, uint16_t to_port, byte *temp_buff, char *extra_data)
{
  memset(_packet, 0, SNMP_MAX_PACKET_LEN);
  _packetPos = SNMP_MAX_PACKET_LEN-1;
  int32_u u;
  int t = 0;
  _extra_data_size = 0;
  
  if(extra_data != NULL){
    _extra_data_size = strlen(extra_data);
  }

  // Varbind List
  if(pdu->type == SNMP_PDU_RESPONSE){
    
    t = pdu->add_data_private(&pdu->value,_packet + _packetPos,true,temp_buff, _extra_data_size);
    _packetPos -= t;
    
    
    //length of entire value being passed
    _packet[_packetPos--] = lsb(t+_extra_data_size);
    _packet[_packetPos--] = msb(t+_extra_data_size);
    _packet[_packetPos--] = 0x82;//Sending length in two octets
    
  }else if(pdu->type == SNMP_PDU_TRAP2 || pdu->type == SNMP_PDU_INFORM_REQUEST){
    //set and increment requestId
    pdu->requestId = requestCounter++;
      
    for (t = pdu->value.size-1; t >= 0; t-- ) {
      _packet[_packetPos--] = pdu->value.data[t];
    }
    //length of entire value being passed
    _packet[_packetPos--] = lsb(pdu->value.size);
    _packet[_packetPos--] = msb(pdu->value.size);
    _packet[_packetPos--] = 0x82;//Sending length in two octets
  }

  _packet[_packetPos--] = (byte)SNMP_SYNTAX_SEQUENCE;// type
  
  // Error Index (size always 4 e.g. 4-byte int)
  u.int32 = pdu->errorIndex;
  _packet[_packetPos--] = u.data[0];
  _packet[_packetPos--] = u.data[1];
  _packet[_packetPos--] = u.data[2];
  _packet[_packetPos--] = u.data[3];
  _packet[_packetPos--] = 0x04;
  _packet[_packetPos--] = (byte)SNMP_SYNTAX_INT;// type

  // Error (size always 4 e.g. 4-byte int)
  u.int32 = pdu->error;
  _packet[_packetPos--] = u.data[0];
  _packet[_packetPos--] = u.data[1];
  _packet[_packetPos--] = u.data[2];
  _packet[_packetPos--] = u.data[3];
  _packet[_packetPos--] = 0x04;
  _packet[_packetPos--] = (byte)SNMP_SYNTAX_INT;// type

  // Request ID (size always 4 e.g. 4-byte int)
  u.int32 = pdu->requestId;
  _packet[_packetPos--] = u.data[0];
  _packet[_packetPos--] = u.data[1];
  _packet[_packetPos--] = u.data[2];
  _packet[_packetPos--] = u.data[3];
  _packet[_packetPos--] = 0x04;
  _packet[_packetPos--] = (byte)SNMP_SYNTAX_INT;// type

  //length value of all previous data
  _packet[_packetPos] = lsb(packet_length()+_extra_data_size);
  _packet[_packetPos-1] = msb(packet_length()+_extra_data_size);
  _packetPos -= 2;
  _packet[_packetPos--] = 0x82;//Sending length in two octets
    
  // SNMP PDU type
  _packet[_packetPos--] = (byte)pdu->type;

  //data needed for header
  _dstType = pdu->type;
  //byte header_size = this->writeHeaders(pdu);
  this->writeHeaders(pdu);
    
  _packetSize = packet_length();
  
//  Serial.println("Outgoing: ");
//  for(byte i = 0; i < _packetSize; i++){
//    Serial.print(_packet[_packetPos+1+i],HEX);
//    Serial.print("-");
//  }
//  Serial.println();
  
  this->writePacket(to_address, to_port, extra_data);

  return pdu->requestId;
}
/* function: ipv4_packet
 * translates an ipv4 packet
 * out    - output packet
 * packet - packet data
 * len    - size of packet
 * returns: the highest position in the output clat_packet that's filled in
 */
int ipv4_packet(clat_packet out, int pos, const char *packet, size_t len) {
  const struct iphdr *header = (struct iphdr *) packet;
  struct ip6_hdr *ip6_targ = (struct ip6_hdr *) out[pos].iov_base;
  uint16_t frag_flags;
  uint8_t nxthdr;
  const char *next_header;
  size_t len_left;
  uint32_t checksum;
  int iov_len;

  if(len < sizeof(struct iphdr)) {
    logmsg_dbg(ANDROID_LOG_ERROR, "ip_packet/too short for an ip header");
    return 0;
  }

  frag_flags = ntohs(header->frag_off);
  if(frag_flags & IP_MF) { // this could theoretically be supported, but isn't
    logmsg_dbg(ANDROID_LOG_ERROR, "ip_packet/more fragments set, dropping");
    return 0;
  }

  if(header->ihl < 5) {
    logmsg_dbg(ANDROID_LOG_ERROR, "ip_packet/ip header length set to less than 5: %x", header->ihl);
    return 0;
  }

  if((size_t) header->ihl * 4 > len) { // ip header length larger than entire packet
    logmsg_dbg(ANDROID_LOG_ERROR, "ip_packet/ip header length set too large: %x", header->ihl);
    return 0;
  }

  if(header->version != 4) {
    logmsg_dbg(ANDROID_LOG_ERROR, "ip_packet/ip header version not 4: %x", header->version);
    return 0;
  }

  /* rfc6145 - If any IPv4 options are present in the IPv4 packet, they MUST be
   * ignored and the packet translated normally; there is no attempt to
   * translate the options.
   */

  next_header = packet + header->ihl*4;
  len_left = len - header->ihl * 4;

  nxthdr = header->protocol;
  if (nxthdr == IPPROTO_ICMP) {
    // ICMP and ICMPv6 have different protocol numbers.
    nxthdr = IPPROTO_ICMPV6;
  }

  /* Fill in the IPv6 header. We need to do this before we translate the packet because TCP and
   * UDP include parts of the IP header in the checksum. Set the length to zero because we don't
   * know it yet.
   */
  fill_ip6_header(ip6_targ, 0, nxthdr, header);
  out[pos].iov_len = sizeof(struct ip6_hdr);

  // Calculate the pseudo-header checksum.
  checksum = ipv6_pseudo_header_checksum(0, ip6_targ, len_left);

  if (nxthdr == IPPROTO_ICMPV6) {
    iov_len = icmp_packet(out, pos + 1, (const struct icmphdr *) next_header, checksum, len_left);
  } else if (nxthdr == IPPROTO_TCP) {
    iov_len = tcp_packet(out, pos + 1, (const struct tcphdr *) next_header, checksum, len_left);
  } else if (nxthdr == IPPROTO_UDP) {
    iov_len = udp_packet(out, pos + 1, (const struct udphdr *) next_header, checksum, len_left);
  } else if (nxthdr == IPPROTO_GRE) {
    iov_len = generic_packet(out, pos + 1, next_header, len_left);
  } else {
#if CLAT_DEBUG
    logmsg_dbg(ANDROID_LOG_ERROR, "ip_packet/unknown protocol: %x",header->protocol);
    logcat_hexdump("ipv4/protocol", packet, len);
#endif
    return 0;
  }

  // Set the length.
  ip6_targ->ip6_plen = htons(packet_length(out, pos));
  return iov_len;
}
예제 #18
0
static inline uint16_t packet_dsize(struct packet_t * packet)
{
    return packet_length(packet) - 5;
}
예제 #19
0
int sick_read_packet(sick_t *s, uint8_t *data)
{
    int res;
    int datalen = 0; // how many bytes of data[] are valid?
    int chk, chk2;
    int want;

readmore:
    //    printf("%i\n", rxlen);
    want = 4 - datalen;
    if (want > 0) {
        // we're willing to wait forever for these bytes
        // (this prevents us from spinning in a poll loop
        res = read_fully_timeout(s->serialfd, &data[datalen], want, -1);
        rxlen += res;
        if (res <= 0)
            return -1;
        datalen += want;
    }

    // two cases: either the 4 bytes consistute a good header, or
    // we skip along to the next occurence of an STX and try
    // again.

    // is this header good?
    int payloadlen = payload_length(data);

    if (data[0] != 0x02   ||   data[1] != 0x80   ||   payloadlen >= (SICK_MAX_MSG_LENGTH - 6)) {
        goto resync;
    }

    // this header is good. read the message (plus checksum bytes)
    want = payloadlen + 6 - datalen;
    if (want > 0) {
        res = read_fully_timeout(s->serialfd, &data[datalen], want, SICK_RX_TIMEOUT_MS);
        rxlen+=res;
        if (res <= 0)
            return -2;
        datalen += want;
    }

    // is the checksum good?
    chk = data[4+payloadlen] + (data[5+payloadlen]<<8);
    chk2 = sick_compute_checksum(data);
    if (chk != chk2) {
        printf("bad chk: %04X != %04X\n", chk, chk2);
        goto resync;
    }

    // good packet received!
    if (s->log_packets_file) {
        for (int i = 0; i < datalen; i++) {
            if (i%16 == 0)
                fprintf(s->log_packets_file, "RX %04x : ", i);
            fprintf(s->log_packets_file, "%02x ", data[i]);
            if ((i%16) == 15 || i+1 == datalen)
                fprintf(s->log_packets_file, "\n");
        }
    }

    // is this the response to a request?
    pthread_mutex_lock(&s->writelock);

    if (s->writedata != NULL && data[4] == s->writereqid) {
        memcpy(s->writedata, data, packet_length(data));
        s->writevalid = 1;
        pthread_cond_signal(&s->writecond);
    }
    pthread_mutex_unlock(&s->writelock);

    // is it a laser scan?
    if (data[4] == 0xb0) {
        sick_handle_scan_b0(s, data);
    } else if (data[4] == 0xf5) {
        sick_handle_scan_f5(s, data);
    }

    return 0;

resync:
    for (int i = 1; i < datalen; i++) {
        if (data[i] == 0x02) {
            memmove(data, &data[i], datalen - i);
            datalen = datalen - i;
            goto readmore;
        }
    }

    // no STX found, start from scratch
    datalen = 0;
    goto readmore;
}