Пример #1
0
void mac_queue_buf_insert(buffer_t *buf)
{
    if (buf)
    {
        list_add(mac_rx_queue, buf);
        debug_dump_buf(buf->dptr, buf->len);
    }
}
Пример #2
0
/*
 * Simulates the sending of data. For the sim interface, the transmission of
 * data means that the data gets sent into the pipe whose destination is
 * the simulator.
 */
U8 drvr_tx(const buffer_t *buf)
{
	DBG_PRINT_RAW("DRVR_TX: ");
	debug_dump_buf(buf->dptr, buf->len);
	tx_len = buf->len;
	sim_pipe_data_out(buf->dptr, buf->len);

	DBG_PRINT("TEST_DRIVER: Frame transmitted.\n");
	return 1;
}
Пример #3
0
static bool skip_rr(u8 *dns, size_t len, size_t *offset) {
	u16 rdlength;
	if (skip_name(dns, len, offset) && ((*offset) + 6) <= len ){
		rdlength = dns[(*offset) + 4] << 8 | dns[(*offset) + 5];
		debug_dump_buf(dns, len, *offset, "skip_rr");
		NFDEBUG("rdlength: %d\n", rdlength);
		if ((*offset) + 6 + rdlength < len) {
			(*offset) += 6 + rdlength;
			return true;
		}
	}
	pr_warn("Skipping RR failed. offset: %zu, len: %zu\n", *offset, len);
	return false;
}
Пример #4
0
static bool skip_name(u8 *dns, size_t len, size_t *offset) {
	/* skip labels */
	debug_dump_buf(dns, len, *offset, "skip_name");
	while (dns[*offset] > 0 && (*offset) < len-4) {
		if (dns[*offset] <= 63)
			(*offset) += dns[*offset] + 1;
		else	{
			(*offset) += 1; /* Compressed label */
			break;
		}
	}
	if (*offset >= len-4) {
		pr_warn(KBUILD_MODNAME ": Tried to skip past packet length! offset: %zu, len: %zu\n",
		        *offset, len);
		return false;
	}
	/* offset is now pointing on the last octet of name */
	(*offset) += 5; /* skip qtype and qclass */
	return true;
}
Пример #5
0
static bool dns_mt(const struct sk_buff *skb, struct xt_action_param *par)
#endif
{
	const struct xt_dns_info *info = par->matchinfo;

	u8 *dns;
	size_t len, offset;
	bool is_match, invert;
	u16 counts[4]; /* qdcount, ancount, nscount, arcount */
	u16 udpsize;
	int i;

	/* skip fragments */
	if (par->fragoff)
		return false;

	NFDEBUG("skb->len: %d, skb->data_len: %d, par->thoff: %d\n", skb->len, skb->data_len, par->thoff);
	/* find UDP payload */
	offset = par->thoff + sizeof(struct udphdr);
	len = skb->len - offset;
	if (len > sizeof(pktbuf)) {
		pr_warn(KBUILD_MODNAME": Packet too big. Increase MAX_MTU (size %d)\n", skb->len);
		return false;
	}
	dns = skb_header_pointer(skb, offset, len, pktbuf);
	if (dns == NULL) {
		pr_warn(KBUILD_MODNAME": skb_header_pointer failed!\n");
		return false;
	}

	/* minimum DNS query payload is 17 bytes (for "." root zone) */
	if (len < 17)
		return false;

	NFDEBUG("skb->len: %d, skb->data_len: %d, len: %zu\n", skb->len, skb->data_len, len);
	debug_dump_buf(dns, len, 0, "ipt_dns");

	/* check if we are dealing with DNS query */
	if (info->flags & XT_DNS_QUERY) {
		invert = ((info->invert_flags & XT_DNS_QUERY) != 0);
		is_match = ((dns[2] & NS_QR) == NS_QR_QUERY);
		if (is_match == invert)
			return false;
	}

	/* check if we are dealing with DNS response */
	if (info->flags & XT_DNS_RESPONSE) {
		invert = ((info->invert_flags & XT_DNS_RESPONSE) != 0);
		is_match = ((dns[2] & NS_QR) == NS_QR_RESPONSE);
		if (is_match == invert)
			return false;
	}

	/* fill counts[] with data from dns header */
	for (i=0; i<4; i++) {
		counts[i] = ntohs(((u16*)dns)[i+2]);
	}

	/* query type test */
	if (info->flags & XT_DNS_QTYPE) {
		NFDEBUG("Entering qtype match\n");
		invert = ((info->invert_flags & XT_DNS_QTYPE) != 0);
		is_match = counts[0] > 0; /* qdcount at least 1 */

		if (!is_match)
			goto qtype_out;

		/* offset is set to the first question section */
		offset = 12;
		is_match = skip_name(dns, len, &offset);
		if (!is_match)
			goto qtype_out;

		NFDEBUG("Matching qtype: %x %x %x %x\n", dns[offset-4], dns[offset-3], dns[offset-2], dns[offset-1]);
		/* match if type=info->type, class IN */
		is_match = (dns[offset-4] == 0x00) && (dns[offset-3] == info->qtype)
			&& (dns[offset-2] == 0x00) && (dns[offset-1] == 0x01);
	
	qtype_out:
		if (is_match == invert)
			return false;
	}

	/* check for EDNS0 */
	if (info->flags & XT_DNS_EDNS0) {
		invert = ((info->invert_flags & XT_DNS_EDNS0) != 0);
		is_match = counts[3] > 0; /* arcount at least 1 */
		
		offset = 12;
		/* skip query sections */
		for (i=0; i<counts[0]; i++) {
			is_match &= skip_name(dns, len, &offset);
			if (!is_match)
				break;
		}
		if (!is_match)
			goto edns0_out;

		/* skip answer and authority sections */
		for (i=0; i<(counts[1]+counts[2]); i++) {
			is_match &= skip_rr(dns, len, &offset);
			if (!is_match)
				break;
		}
		if (!is_match)
			goto edns0_out;

		/* try to find EDNS0 pseudo-RR */
		for (i=0; i<counts[3]; i++) {
			if (dns[offset] == 0 && dns[offset+1] == 0 && dns[offset+2] == 41)
				break;
			is_match &= skip_rr(dns, len, &offset);
			if (!is_match)
				break;
		}
		if (!is_match || (i == counts[3])) {
			is_match = false;
			goto edns0_out;
		}
		/* EDNS0 found */
		if (info->flags & XT_DNS_BUFSIZE) {
			/* TODO: XT_DNS_BUFSIZE inversion not implemented */
			udpsize = dns[offset+3] << 8 | dns[offset+4];
			if (udpsize < info->bufsize[0] || udpsize > info->bufsize[1]) {
				is_match = false;
				goto edns0_out;
			}
		}
		debug_dump_buf(dns, len, offset, "ipt_dns_edns0");
	edns0_out:
		if (is_match == invert)
			return false;
		
	}

	/* Nothing stopped us so far, let's accept the packet */
	return true;
}
Пример #6
0
static void *on_stdin_read(oop_source *oop_src, int std_in, 
			   oop_event event, void *ctx)
{
  ruli_res_t *res_ctx = (ruli_res_t *) ctx;
  int        result;
  const int  QBUF_SIZE = sizeof(srv_qbuf_t);

  assert(std_in == 0);
  assert(event == OOP_READ);

  /*
   * Read stdin
   */

  result = read_stdin(std_in);

  switch (result) {
  case STDIN_READ_OK:
    break;

  case STDIN_READ_BLOCK:
    return OOP_CONTINUE;

  case STDIN_READ_EOF:
    /* Stop monitoring stdin */
    oop_src->cancel_fd(oop_src, std_in, OOP_READ);
    return OOP_CONTINUE;

  case STDIN_READ_ERROR:
    return OOP_HALT;

  case STDIN_READ_OVERFLOW:
    fprintf(stderr, 
	    "%s: on_stdin_read(): stdin read buffer overflow\n", 
	    prog_name);
    reset_stdin_buf();
    return OOP_CONTINUE;

  default:
    assert(0); /* NOT REACHED */
  }

  /*
   * Scan possible hostnames from stdin
   */
  for (;;) {

    srv_qbuf_t *qbuf;

    /* plain domain */
    const int domain_buf_size = IN_BUF_SIZE;
    char      domain[domain_buf_size];
    int       domain_len;
    
    /*
     * Parse hostname
     */

    result = get_next_domain(domain, domain_buf_size, &domain_len);
    
    /* If no domain found yet, keep waiting for one */
    if (result == PARSE_DOMAIN_NONE)
      return OOP_CONTINUE;
    
    /* Do not expect other errors, not even overflow */
    assert(!result);

    /*
     * Now we have the full domain name, submit a query for it
     */

    /*
     * Break full domain name in service + domain into qbuf
     */

    {
      char *past_end = domain + domain_len;
      char *i = domain;

      for (; i < past_end; ++i) {
	if (*i == '.') {
	  ++i;
	  if (i < past_end) {
	    if (*i != '_')
	      break;
	  }
	}
      }

      if (i >= past_end) {
	fprintf(stderr, 
		"%s: on_stdin_read(): could not split service/domain\n",
		prog_name);

	return OOP_CONTINUE;
      }

      /* Allocate qbuf */
      qbuf = (srv_qbuf_t *) malloc(QBUF_SIZE);
      if (!qbuf) {
	fprintf(stderr, 
		"%s: on_stdin_read(): could not allocate srv_qbuf_t: malloc(%d) failed\n",
		prog_name, QBUF_SIZE);
	
	return OOP_CONTINUE;
      }

      qbuf->txt_service_len = i - domain - 1;
      assert(qbuf->txt_service_len < QBUFSZ);
      memcpy(qbuf->txt_service, domain, qbuf->txt_service_len);
      qbuf->txt_service[qbuf->txt_service_len] = '\0';
      
#ifdef SRVSOLVER_DEBUG
      debug_dump_buf(stderr, 
		     "on_stdin_read(): txt_service=%s txt_service_len=%d", 
		     qbuf->txt_service, qbuf->txt_service_len);
#endif

      qbuf->txt_domain_len = past_end - i;
      assert(qbuf->txt_domain_len < QBUFSZ);
      memcpy(qbuf->txt_domain, i, qbuf->txt_domain_len);
      qbuf->txt_domain[qbuf->txt_domain_len] = '\0';

#ifdef SRVSOLVER_DEBUG
      debug_dump_buf(stderr, 
		     "on_stdin_read(): txt_domain=%s txt_domain_len=%d", 
		     qbuf->txt_domain, qbuf->txt_domain_len);
#endif
    }

    /*
     * Encode buffers in qbuf (txt => raw)
     */

    if (encode_srv_qbuf(qbuf)) {
      fprintf(stderr, 
	      "%s: on_stdin_read(): could not encode domain in srv_qbuf_t\n",
	      prog_name);

      free(qbuf);

      return OOP_CONTINUE;
    }
        
    /*
     * Send query
     */
    
    {
      ruli_srv_t *srv_qry = submit_query(res_ctx, qbuf);
      if (!srv_qry) {
	fprintf(stderr, 
		"%s: on_stdin_read(): could not send SRV query\n",
		prog_name);

	free(qbuf);
	
	return OOP_CONTINUE;
      }
    }
    
  } /* for loop */

  assert(0); /* NOT REACHED */

  return OOP_CONTINUE;
}
Пример #7
0
/*
 * Handle the rx events from the mac process. If the driver
 * receives a valid frame, it will send an event to the mac
 * process. The mac process will then call the event handler
 * which retrieves the frame from the rx queue and parses it.
 * Once parsed, it will be handled according to the frame type.
 * If its a command frame, it gets sent to the command handler,
 * a data frame gets sent to the next higher layer, etc...
 */
static void mac_eventhandler(process_event_t event)
{
	buffer_t *buf, *buf_out;
	mac_hdr_t hdr;
	mac_cmd_t cmd;
	bool frm_pend;
	mac_pcb_t *pcb = mac_pcb_get();
	mac_pib_t *pib = mac_pib_get();

	if (event == event_mac_rx)
	{
		DBG_PRINT("MAC_EVENTHANDLER: Rx event occurred.\n");

		buf = mac_queue_buf_pop();
		if (buf) {
			DBG_PRINT_RAW("\n<INCOMING>");
			debug_dump_buf(buf->dptr, buf->len);

			/* decode the packet */
			mac_parse_hdr(buf, &hdr);
			debug_dump_mac_hdr(&hdr);

			/*
			 * check if an ack is needed. if so, then generate
			 * an ack and queue it for transmission. the frm
			 * pending bit will be set for any frame coming from
			 * an address that has an indirect frame for it. this
			 * is against the spec, but it will speed up the ack
			 * transmission.
			 * NOTE: the ack response section may change due to the
			 * tight ack timing requirements.
			 */
			if (hdr.mac_frm_ctrl.ack_req)
			{
				BUF_ALLOC(buf_out, TX);
				DBG_PRINT("MAC: ACK Required.\n");
				frm_pend = mac_indir_frm_pend(&hdr.src_addr);
				mac_gen_ack(buf_out, frm_pend, hdr.dsn);
				mac_out(buf_out, false, hdr.dsn, 0);
			}

			/*
			 * process accordingly. if a scan is in progress,
			 * all frames except for beacon frames will be
			 * discarded.
			 */
			switch(hdr.mac_frm_ctrl.frame_type)
			{
			case MAC_COMMAND:
				if (pcb->mac_state != MLME_SCAN)
				{
					/*
					 * need to handle the case that this is an indirect
					 * transfer, which means that we need to stop the
					 * poll timer and send a status to the poll confirm.
					 */
					if ((pcb->mac_state == MLME_DATA_REQ) &&
					(hdr.src_addr.mode == SHORT_ADDR) &&
					(hdr.src_addr.short_addr == pib->coord_addr.short_addr))
					{
						ctimer_stop(&pcb->mlme_tmr);
						mac_poll_conf(MAC_SUCCESS);
					}

					mac_parse_cmd(buf, &cmd);
					mac_cmd_handler(&cmd, &hdr);
				}
				buf_free(buf);
				break;
			case MAC_BEACON:
				/* discard the beacon if we're not doing a scan */
				if (pcb->mac_state == MLME_SCAN)
				{
					mac_parse_beacon(buf, &hdr);
					mac_beacon_notify_ind(buf, mac_scan_descr_find_addr(&hdr.src_addr));
				}
				buf_free(buf);
				break;
			case MAC_ACK:
				mac_retry_ack_handler(hdr.dsn);

				/*
				 * we need to do some special ops depending on the
				 * state we're in if we get an ACK.
				 */
				if (pcb->mac_state == MLME_ASSOC_REQ)
				{
					if (pcb->assoc_req_dsn == hdr.dsn)
						ctimer_set(&pcb->mlme_tmr,
							   pib->resp_wait_time,
							   mac_poll_req,
							   NULL);
				} else if (pcb->mac_state == MLME_DATA_REQ) {
					if (hdr.mac_frm_ctrl.frame_pending)
						ctimer_set(&pcb->mlme_tmr,
							   aMacMaxFrameTotalWaitTime,
							   mac_poll_timeout,
							   NULL);
				}
				buf_free(buf);
				break;
			case MAC_DATA:
				if (pcb->mac_state != MLME_SCAN)
				{
					/*
					 * need to handle the case that this is an indirect
					 * transfer, which means that we need to stop the poll
					 * timer and send a status to the poll confirm.
					 */
					if ((pcb->mac_state == MLME_DATA_REQ)  &&
						(hdr.src_addr.mode == SHORT_ADDR) &&
						(hdr.src_addr.short_addr == pib->coord_addr.short_addr))
					{
						ctimer_stop(&pcb->mlme_tmr);
						mac_poll_conf(MAC_SUCCESS);
					}

					mac_data_ind(buf, &hdr);
				} else
					buf_free(buf);
				break;
			default:
				/* TODO: Add a statistic here to capture an error'd rx */
			break;
			}
		}
		/*
		 * there's a possibility that more than one frame is in the
		 * buffer. if they came in before this function gets executed.
		 * So process until the queue is empty.
		 */
		if (!mac_queue_is_empty())
		{
			while (process_post(&mac_process, event_mac_rx, NULL) != PROCESS_ERR_OK)
			{
				;
			}
		}
	}
}