Ejemplo n.º 1
0
/*
 * Class:     net_RawIPv6Socket
 * Method:    _bind
 * Signature: (I[BI)I
 */
JNIEXPORT jint JNICALL Java_net_RawIPv6Socket__1bind
  (JNIEnv *env, jobject obj, jint socket, jbyteArray address, jint scopeid) {
    struct sockaddr *saddr;
    struct sockaddr_in6 sin6;
    saddr = fill_sockaddr_in6(env, &sin6, address,scopeid);

    return bind(socket, saddr, sizeof(sin6));
}
Ejemplo n.º 2
0
status_t
IPv6Multicast::LeaveGroup(IPv6GroupInterface* state)
{
	MutexLocker _(sMulticastGroupsLock);

	sMulticastState->Remove(state);

	sockaddr_in6 groupAddr;
	return sDatalinkModule->leave_multicast(state->Interface(), sDomain,
		fill_sockaddr_in6(&groupAddr, state->Address()));
}
Ejemplo n.º 3
0
status_t
IPv6Multicast::JoinGroup(IPv6GroupInterface* state)
{
	MutexLocker _(sMulticastGroupsLock);

	sockaddr_in6 groupAddr;
	status_t status = sDatalinkModule->join_multicast(state->Interface(),
		sDomain, fill_sockaddr_in6(&groupAddr, state->Address()));
	if (status != B_OK)
		return status;

	sMulticastState->Insert(state);
	return B_OK;
}
Ejemplo n.º 4
0
status_t
ipv6_receive_data(net_buffer* buffer)
{
	TRACE("ReceiveData(%p [%ld bytes])", buffer, buffer->size);

	NetBufferHeaderReader<IPv6Header> bufferHeader(buffer);
	if (bufferHeader.Status() != B_OK)
		return bufferHeader.Status();

	IPv6Header &header = bufferHeader.Data();
	// dump_ipv6_header(header);

	if (header.ProtocolVersion() != IPV6_VERSION)
		return B_BAD_TYPE;

	uint16 packetLength = header.PayloadLength() + sizeof(ip6_hdr);
	if (packetLength > buffer->size)
		return B_BAD_DATA;

	// lower layers notion of Broadcast or Multicast have no relevance to us
	buffer->flags &= ~(MSG_BCAST | MSG_MCAST);

	sockaddr_in6 destination;
	fill_sockaddr_in6(&destination, header.Dst());

	if (IN6_IS_ADDR_MULTICAST(&destination.sin6_addr)) {
		buffer->flags |= MSG_MCAST;
	} else {
		uint32 matchedAddressType = 0;

		// test if the packet is really for us
		if (!sDatalinkModule->is_local_address(sDomain, (sockaddr*)&destination,
				&buffer->interface_address, &matchedAddressType)
			&& !sDatalinkModule->is_local_link_address(sDomain, true,
				buffer->destination, &buffer->interface_address)) {

			char srcbuf[INET6_ADDRSTRLEN];
			char dstbuf[INET6_ADDRSTRLEN];
			ip6_sprintf(&header.Src(), srcbuf);
			ip6_sprintf(&header.Dst(), dstbuf);
			TRACE("  ipv6_receive_data(): packet was not for us %s -> %s",
				srcbuf, dstbuf);

			// TODO: Send ICMPv6 error: Host unreachable
			return B_ERROR;
		}

		// copy over special address types (MSG_BCAST or MSG_MCAST):
		buffer->flags |= matchedAddressType;
	}

	// set net_buffer's source/destination address
	fill_sockaddr_in6((struct sockaddr_in6*)buffer->source, header.Src());
	memcpy(buffer->destination, &destination, sizeof(sockaddr_in6));

	// get the transport protocol and transport header offset
	uint16 transportHeaderOffset = header.GetHeaderOffset(buffer);
	uint8 protocol = buffer->protocol;

	// remove any trailing/padding data
	status_t status = gBufferModule->trim(buffer, packetLength);
	if (status != B_OK)
		return status;

	// check for fragmentation
	uint16 fragmentHeaderOffset
		= header.GetHeaderOffset(buffer, IPPROTO_FRAGMENT);

	if (fragmentHeaderOffset != 0) {
		// this is a fragment
		TRACE("  ipv6_receive_data(): Found a Fragment!");
		status = reassemble_fragments(header, &buffer, fragmentHeaderOffset);
		TRACE("  ipv6_receive_data():  -> %s", strerror(status));
		if (status != B_OK)
			return status;

		if (buffer == NULL) {
			// buffer was put into fragment packet
			TRACE("  ipv6_receive_data(): Not yet assembled.");
			return B_OK;
		}
	}

	// tell the buffer to preserve removed ipv6 header - may need it later
	gBufferModule->store_header(buffer);

	// remove ipv6 headers for now
	gBufferModule->remove_header(buffer, transportHeaderOffset);

	// deliver the data to raw sockets
	raw_receive_data(buffer);

	net_protocol_module_info* module = receiving_protocol(protocol);
	if (module == NULL) {
		// no handler for this packet
		return EAFNOSUPPORT;
	}

	if ((buffer->flags & MSG_MCAST) != 0) {
		// Unfortunately historical reasons dictate that the IP multicast
		// model be a little different from the unicast one. We deliver
		// this frame directly to all sockets registered with interest
		// for this multicast group.
		return deliver_multicast(module, buffer, false);
	}

	return module->receive_data(buffer);
}
Ejemplo n.º 5
0
/*
 * Class:     net_RawIPv6Socket
 * Method:    _send
 * Signature: (I[B[BI[BII)I
 */
JNIEXPORT jint JNICALL Java_net_RawIPv6Socket__1send
  (JNIEnv *env, jobject obj, jint socket, jbyteArray srcaddress, jbyteArray dstaddress, jint dstscopeid,
        jbyteArray data, jint offset, jint len, jint ttl, jint tos) {
    int result;
    jbyte *buf;
    struct sockaddr_in6 sin6;
    struct sockaddr *saddr;
    struct msghdr mhdr;
    struct iovec iovecs[1];
    char msg_control_buffer6[CMSG_SPACE(sizeof(int))+CMSG_SPACE(sizeof(int))+CMSG_SPACE(sizeof(struct in6_pktinfo))]; 
    struct cmsghdr *cmsg;
    int controllen;
    struct in6_pktinfo *pktinfo6;
    int *sent_ttl;
    int *sent_tos;
    
    saddr = fill_sockaddr_in6(env, &sin6, dstaddress, dstscopeid);
 

    buf = (*env)->GetByteArrayElements(env, data, NULL);

    mhdr.msg_name = saddr;
    mhdr.msg_namelen = sizeof(sin6);
    iovecs[0].iov_base= &buf[offset];
    iovecs[0].iov_len = len;
    mhdr.msg_iov = &iovecs[0];
    mhdr.msg_iovlen = 1;
    mhdr.msg_control = msg_control_buffer6;
    mhdr.msg_controllen = sizeof(msg_control_buffer6);
    controllen = 0;
    cmsg = CMSG_FIRSTHDR(&mhdr);
    cmsg->cmsg_level = IPPROTO_IPV6;
    cmsg->cmsg_type = IPV6_PKTINFO;
    cmsg->cmsg_len = 0;
    pktinfo6 = (struct in6_pktinfo*) CMSG_DATA(cmsg);
    pktinfo6->ipi6_ifindex = 0;
    pktinfo6->ipi6_addr = in6addr_any;//source address not specified 
    if (srcaddress != NULL)
        init_addr(env,&pktinfo6->ipi6_addr,srcaddress,sizeof(struct in6_addr));
    controllen += CMSG_SPACE(sizeof(struct in6_pktinfo));  
    cmsg = (struct cmsghdr *)((unsigned char*)cmsg + CMSG_SPACE(sizeof(struct in6_pktinfo)));
    
    if (ttl >=0) {
        
        cmsg->cmsg_level = IPPROTO_IPV6;
        cmsg->cmsg_type = IPV6_HOPLIMIT;
        cmsg->cmsg_len = CMSG_LEN(sizeof(int));
        sent_ttl = (int *)CMSG_DATA(cmsg);
        *sent_ttl = ttl;
        controllen += CMSG_SPACE(sizeof(int));
        cmsg = (struct cmsghdr *)((unsigned char*)cmsg + CMSG_SPACE(sizeof(int)));
    }
    if (tos >=0) {
        cmsg = CMSG_NXTHDR(&mhdr,cmsg);
        cmsg->cmsg_level = IPPROTO_IPV6;
        cmsg->cmsg_type = IPV6_TCLASS;
        cmsg->cmsg_len = CMSG_LEN(sizeof(int));
        sent_tos = (int *)CMSG_DATA(cmsg);
        *sent_tos = tos;
        controllen += CMSG_SPACE(sizeof(int));
        cmsg = (struct cmsghdr *)((unsigned char*)cmsg + CMSG_SPACE(sizeof(int)));
    }
    mhdr.msg_controllen = controllen;
    
    result = sendmsg(socket,&mhdr,0);

    (*env)->ReleaseByteArrayElements(env, data, buf, JNI_ABORT);

    return result;
}