示例#1
0
文件: packetsrv.c 项目: regit/nufw
/**
 * \brief Callback called by NetFilter when a packet with target QUEUE is matched.
 *
 * For TCP packet with flags different than SYN, just send it to NuAuth and
 * accept it.
 *
 * For other packet: First of all, fill a structure ::packet_idl (identifier,
 * timestamp, ...). Try to add the new packet to ::packets_list (fails if the
 * list is full). Ask an authentication to NuAuth using auth_request_send(),
 * If the packet can't be sended, remove it from the list.
 *
 * \return If an error occurs, returns 0, else returns 1.
 */
static int treat_packet(struct nfq_handle *qh, struct nfgenmsg *nfmsg,
			struct nfq_data *nfa, void *data)
{
	packet_idl *current;
	struct queued_pckt q_pckt;
	struct nfqnl_msg_packet_hdr *ph;
	struct timeval timestamp;
	int ret;
#ifdef HAVE_NFQ_INDEV_NAME
	struct nlif_handle *nlif_handle = (struct nlif_handle *) data;
#endif

	debug_log_printf(DEBUG_AREA_PACKET, DEBUG_LEVEL_VERBOSE_DEBUG,
			 "(*) New packet");

	q_pckt.payload_len = nfq_get_payload(nfa, &(q_pckt.payload));
	if (q_pckt.payload_len == -1) {
		log_area_printf(DEBUG_AREA_PACKET, DEBUG_LEVEL_INFO,
				"Unable to get payload");
		return 0;
	}

	q_pckt.mark = nfq_get_nfmark(nfa);

#ifdef HAVE_NFQ_INDEV_NAME
	if (!get_interface_information(nlif_handle, &q_pckt, nfa)) {
		log_area_printf(DEBUG_AREA_PACKET, DEBUG_LEVEL_INFO,
				"Can not get interfaces information for message");
		return 0;
	}
#else
	snprintf(q_pckt.indev, sizeof(q_pckt.indev), "*");
	snprintf(q_pckt.physindev, sizeof(q_pckt.physindev), "*");
	snprintf(q_pckt.outdev, sizeof(q_pckt.outdev), "*");
	snprintf(q_pckt.physoutdev, sizeof(q_pckt.physoutdev), "*");
#endif

	ret = nfq_get_timestamp(nfa, &timestamp);
	if (ret == 0) {
		q_pckt.timestamp = timestamp.tv_sec;
	} else {
		q_pckt.timestamp = time(NULL);
	}

	if (look_for_tcp_flags
	    ((unsigned char *) q_pckt.payload, q_pckt.payload_len)) {
		ph = nfq_get_msg_packet_hdr(nfa);
		if (ph) {
			q_pckt.packet_id = ntohl(ph->packet_id);
			auth_request_send(AUTH_CONTROL, &q_pckt);
			IPQ_SET_VERDICT(q_pckt.packet_id, NF_ACCEPT);
			RETURN_NO_LOG 1;
		} else {
			log_area_printf(DEBUG_AREA_PACKET, DEBUG_LEVEL_VERBOSE_DEBUG,
					"Can not get the packet headers");
			return 0;
		}
	}
	current = calloc(1, sizeof(packet_idl));
	current->nfmark = q_pckt.mark;
	current->timestamp = q_pckt.timestamp ;
	current->id = 0;
	if (current == NULL) {
		log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_MESSAGE,
				"Can not allocate packet_id");
		return 0;
	}
#ifdef PERF_DISPLAY_ENABLE
	gettimeofday(&(current->arrival_time), NULL);
#endif
	/* Get unique identifier of packet in queue */
	ph = nfq_get_msg_packet_hdr(nfa);
	if (ph) {
		current->id = ntohl(ph->packet_id);
	} else {
		free(current);
		log_area_printf(DEBUG_AREA_PACKET, DEBUG_LEVEL_INFO,
				"Can not get id for message");
		return 0;
	}

	/* Try to add the packet to the list */
	ret = padd(current);
	q_pckt.packet_id = current->id;

	if (ret == 0) {
		/* send an auth request packet */
		if (!auth_request_send(AUTH_REQUEST, &q_pckt)) {
			int sandf = 0;
			/* send failure dropping packet */
			IPQ_SET_VERDICT(q_pckt.packet_id, NF_DROP);
			/* we fail to send the packet so we free packet related to current */
			/* search and destroy packet by packet_id */
			sandf = psearch_and_destroy(q_pckt.packet_id,
						&(q_pckt.mark));

			if (!sandf) {
				log_area_printf(DEBUG_AREA_MAIN,
						DEBUG_LEVEL_WARNING,
						"Packet could not be removed: %u",
						q_pckt.packet_id);
			}
		}
	}
	return 1;
}
示例#2
0
/**
 * Process NuAuth message of type #AUTH_ANSWER
 */
int auth_process_answer(char *dgram, int dgram_size)
{
	nuv5_nuauth_decision_response_t *answer;
	uint32_t nfmark;
	int sandf;
	u_int32_t packet_id;
	int payload_len;
	int msg_len;

	/* check packet size */
	if (dgram_size < (int) sizeof(nuv4_nuauth_decision_response_t)) {
		return -1;
	}
	answer = (nuv5_nuauth_decision_response_t *) dgram;

	/* check payload length */
	payload_len = ntohs(answer->payload_len);
	msg_len = payload_len + sizeof(nuv5_nuauth_decision_response_t);
	if (dgram_size < msg_len) {
		log_area_printf(DEBUG_AREA_GW, DEBUG_LEVEL_WARNING,
				"[!] Packet with improper size: payload of %d, received %d (vs %d)",
				payload_len,
				dgram_size,
				(int) (sizeof(nuv5_nuauth_decision_response_t) + payload_len));
		return -1;
	}

	/* get packet id and user id */
	packet_id = ntohl(answer->packet_id);

	/* search and destroy packet by packet_id */
	sandf = psearch_and_destroy(packet_id, &nfmark);
	if (!sandf) {
		log_area_printf(DEBUG_AREA_GW | DEBUG_AREA_GW,
				DEBUG_LEVEL_WARNING,
				"[!] Packet without a known ID: %u",
				packet_id);
		return -1;
	}

	switch (answer->decision) {
	case DECISION_ACCEPT:
		/* accept packet */
		debug_log_printf(DEBUG_AREA_PACKET,
				 DEBUG_LEVEL_VERBOSE_DEBUG,
				 "(*) Accepting packet with id=%u",
				 packet_id);
		if (nufw_set_mark) {
			debug_log_printf(DEBUG_AREA_PACKET,
					 DEBUG_LEVEL_VERBOSE_DEBUG,
					 "(*) Marking packet with %d",
					 ntohl(answer->tcmark));
#if HAVE_NFQ_MARK_EXPTIME
			if (ntohl(answer->expiration) != -1) {
				IPQ_SET_VWMARK_EXPTIME(packet_id, NF_ACCEPT,
					       answer->tcmark,
					       ntohl(answer->expiration));
			} else {
				IPQ_SET_VWMARK(packet_id, NF_ACCEPT,
					       answer->tcmark);
			}
#else
			IPQ_SET_VWMARK(packet_id, NF_ACCEPT,
				       answer->tcmark);
#endif
		} else {
			IPQ_SET_VERDICT(packet_id, NF_ACCEPT);
		}
		pckt_tx++;
		break;

	case DECISION_REJECT:
		/* Packet is rejected, ie. dropped and ICMP signalized */
		log_area_printf(DEBUG_AREA_PACKET, DEBUG_LEVEL_VERBOSE_DEBUG,
				"(*) Rejecting %" PRIu32, packet_id);
		IPQ_SET_VERDICT(packet_id, NF_DROP);
		if (send_icmp_unreach(dgram +
				  sizeof(nuv5_nuauth_decision_response_t),
				  payload_len) == -1) {
			log_area_printf(DEBUG_AREA_PACKET, DEBUG_LEVEL_WARNING,
					"(*) Could not sent ICMP reject for %" PRIu32, packet_id);
		}
		break;

	default:
		/* drop packet */
		debug_log_printf(DEBUG_AREA_PACKET,
				 DEBUG_LEVEL_VERBOSE_DEBUG,
				 "(*) Drop packet %u", packet_id);
		IPQ_SET_VERDICT(packet_id, NF_DROP);
	}
	return msg_len;
}