Esempio n. 1
0
int
isns_authblock_decode(buf_t *bp, struct isns_authblk *auth)
{
	unsigned int	avail = buf_avail(bp);

	if (!buf_get32(bp, &auth->iab_bsd)
	 || !buf_get32(bp, &auth->iab_length)
	 || !buf_get64(bp, &auth->iab_timestamp)
	 || !buf_get32(bp, &auth->iab_spi_len))
		 return 0;

	/* Make sure the length specified by the auth block
	 * is reasonable. */
	if (auth->iab_length < ISNS_AUTHBLK_SIZE
	 || auth->iab_length > avail)
		return 0;

	/* This chops off any data trailing the auth block.
	 * It also makes sure that we detect if iab_length
	 * exceeds the amount of available data. */
	if (!buf_truncate(bp, auth->iab_length - ISNS_AUTHBLK_SIZE))
		return 0;

	auth->iab_spi = buf_head(bp);
	if (!buf_pull(bp, auth->iab_spi_len))
		return 0;

	auth->iab_sig = buf_head(bp);
	auth->iab_sig_len = buf_avail(bp);
	return 1;
}
Esempio n. 2
0
/*
 * Receive interrupt task.
 */
static void
slip_receiver (void *arg)
{
    slip_t *u = arg;
    unsigned short len;

    /* Start receiver. */
    mutex_lock_irq (&u->netif.lock, RECEIVE_IRQ (u->port),
                    (handler_t) slip_receive_data, u);

    enable_receiver (u->port);
    enable_receive_interrupt (u->port);

    for (;;) {
        if (! u->in_ptr) {
            /* Allocate buffer for receive data. */
            u->in = buf_alloc (u->pool, u->netif.mtu, 16);
            if (u->in) {
                u->in_ptr = u->in->payload;
                u->in_limit = u->in_ptr + u->netif.mtu;
            } else {
                /* No buffer - ignore input. */
                debug_printf ("slip_receiver: out of memory\n");
                ++u->netif.in_discards;
            }
        }

        /* Wait for the receive interrupt. */
        mutex_wait (&u->netif.lock);

        /* Process all available received data. */
        if (u->in_ptr && u->in_ptr > u->in->payload) {
            len = u->in_ptr - u->in->payload;
            debug_printf ("slip_receiver(%ld): received %d bytes\n", u->netif.in_packets, len);
            buf_truncate (u->in, len);
            ++u->netif.in_packets;

            if (buf_queue_is_full (&u->inq)) {
                debug_printf ("slip_receiver: input overflow\n");
                ++u->netif.in_discards;

                /* Reuse the packet. */
                u->in_ptr = u->in->payload;
                u->in_limit = u->in_ptr + u->netif.mtu;
            } else {
                /* Enqueue the received packet. */
                buf_queue_put (&u->inq, u->in);
                u->in_ptr = 0;
            }
        }
#ifndef TRANSMIT_IRQ
        if (u->out_free)
            slip_out_next (u);
#endif
    }
}
Esempio n. 3
0
/* Print the build information as flattened properties, prefixed by
 * the contents of buf. */
static void format_flat(json_t *buildinfo, struct buf *buf)
{
    const char *key;
    json_t *val;

    json_object_foreach(buildinfo, key, val) {
        buf_appendcstr(buf, key);
        if (json_typeof(val) == JSON_OBJECT) {
            buf_appendcstr(buf, ".");
            format_flat(val, buf);
            buf_truncate(buf, -1);
        } else {
            char *jval = json_dumps(val, JSON_ENCODE_ANY);
            buf_appendcstr(buf, "=");
            buf_appendcstr(buf, jval);
            printf("%s\n", buf_cstring(buf));
            buf_truncate(buf, -strlen(jval)-1);
            free(jval);
        }
        buf_truncate(buf, -strlen(key));
    }
Esempio n. 4
0
/*
 * Create ARP request packet.
 * Argument `ipsrc' is the IP address of the network interface,
 * from which we send the ARP request. The network interface could have
 * several IP adresses (aliases), so ipsrc is needed to select
 * concrete alias.
 */
bool_t
arp_request (netif_t *netif, buf_t *p, unsigned char *ipdest,
	unsigned char *ipsrc)
{
	struct arp_hdr *ah;

	/* ARP packet place at the begin of buffer (offset 2) */
	buf_add_header (p, p->payload - (unsigned char*) p - sizeof (buf_t) - 2);

	if (p->tot_len < sizeof (struct arp_hdr)) {
		/* Not enough space for ARP packet. */
		buf_free (p);
		return 0;
	}
	buf_truncate (p, sizeof (struct arp_hdr));
	p = buf_make_continuous (p);

	ah = (struct arp_hdr*) p->payload;
	ah->eth.proto = PROTO_ARP;
	memcpy_flash (ah->eth.dest, BROADCAST, 6);
	memcpy (ah->eth.src, netif->ethaddr, 6);

	ah->opcode = ARP_REQUEST;
	ah->hwtype = HWTYPE_ETHERNET;
	ah->hwlen = 6;
	ah->proto = PROTO_IP;
	ah->protolen = 4;

	/* Most implementations set dst_hwaddr to zero. */
	memset (ah->dst_hwaddr, 0, 6);
	memcpy (ah->src_hwaddr, netif->ethaddr, 6);
	memcpy (ah->dst_ipaddr, ipdest, 4);
	memcpy (ah->src_ipaddr, ipsrc, 4);

	/* debug_printf ("arp: send request for %d.%d.%d.%d\n",
		ipdest[0], ipdest[1], ipdest[2], ipdest[3]); */
	/*debug_printf ("     from %d.%d.%d.%d %02x-%02x-%02x-%02x-%02x-%02x\n",
		ipsrc[0], ipsrc[1], ipsrc[2], ipsrc[3],
		netif->ethaddr[0], netif->ethaddr[1], netif->ethaddr[2],
		netif->ethaddr[3], netif->ethaddr[4], netif->ethaddr[5]);*/
	return netif->interface->output (netif, p, 0);
}
Esempio n. 5
0
/*
 * Process the packet, received by adapter.
 * Process ARP requests. For IP packets, strip off the ethernet header.
 */
buf_t *
arp_input (netif_t *netif, buf_t *p)
{
	struct ethip_hdr *h;
	struct arp_hdr *ah;
	unsigned char *ipaddr;

	/*debug_printf ("arp_input: %d bytes\n", p->tot_len);*/
	h = (struct ethip_hdr*) p->payload;
	switch (h->eth.proto) {
	default:
		/* Unknown protocol. */
		/* debug_printf ("arp_input: unknown protocol 0x%x\n", h->eth.proto); */
		buf_free (p);
		return 0;

	case PROTO_IP:
		/*debug_printf ("arp: ip packet from %d.%d.%d.%d %02x-%02x-%02x-%02x-%02x-%02x\n",
			h->ip_src[0], h->ip_src[1], h->ip_src[2], h->ip_src[3],
			h->eth.src[0], h->eth.src[1], h->eth.src[2],
			h->eth.src[3], h->eth.src[4], h->eth.src[5]);*/

		/* For unicasts, update an ARP entry, independent of
		 * the source IP address. */
		if (h->eth.dest[0] != 255) {
			/* debug_printf ("arp: add entry %d.%d.%d.%d %02x-%02x-%02x-%02x-%02x-%02x\n",
				h->ip_src[0], h->ip_src[1], h->ip_src[2], h->ip_src[3],
				h->eth.src[0], h->eth.src[1], h->eth.src[2],
				h->eth.src[3], h->eth.src[4], h->eth.src[5]); */
			arp_add_entry (netif, h->ip_src, h->eth.src);
		}

		/* Strip off the Ethernet header. */
		buf_add_header (p, -14);
		return p;

	case PROTO_ARP:
		if (p->tot_len < sizeof (struct arp_hdr)) {
			/* debug_printf ("arp_input: too short packet\n"); */
			buf_free (p);
			return 0;
		}
		buf_truncate (p, sizeof (struct arp_hdr));
		p = buf_make_continuous (p);

		ah = (struct arp_hdr*) p->payload;
		switch (ah->opcode) {
		default:
			/* Unknown ARP operation code. */
			/* debug_printf ("arp_input: unknown opcode 0x%x\n", ah->opcode); */
			buf_free (p);
			return 0;

		case ARP_REQUEST:
#ifdef ARP_TRACE
			debug_printf ("arp: got request for %d.%d.%d.%d\n",
				ah->dst_ipaddr[0], ah->dst_ipaddr[1], ah->dst_ipaddr[2], ah->dst_ipaddr[3]);
			debug_printf ("     from %d.%d.%d.%d %02x-%02x-%02x-%02x-%02x-%02x\n",
				ah->src_ipaddr[0], ah->src_ipaddr[1], ah->src_ipaddr[2], ah->src_ipaddr[3],
				ah->src_hwaddr[0], ah->src_hwaddr[1], ah->src_hwaddr[2],
				ah->src_hwaddr[3], ah->src_hwaddr[4], ah->src_hwaddr[5]);
#endif
			/* ARP request. If it asked for our address,
			 * we send out a reply. */
			ipaddr = route_lookup_ipaddr (netif->arp->ip,
				ah->src_ipaddr, netif);
			if (! ipaddr || memcmp (ipaddr, ah->dst_ipaddr, 4) != 0) {
				buf_free (p);
				return 0;
			}

			ah->opcode = ARP_REPLY;

			memcpy (ah->dst_ipaddr, ah->src_ipaddr, 4);
			memcpy (ah->src_ipaddr, ipaddr, 4);

			memcpy (ah->dst_hwaddr, ah->src_hwaddr, 6);
			memcpy (ah->src_hwaddr, netif->ethaddr, 6);
			memcpy (ah->eth.dest, ah->dst_hwaddr, 6);
			memcpy (ah->eth.src, netif->ethaddr, 6);

			ah->eth.proto = PROTO_ARP;
#ifdef ARP_TRACE
			debug_printf ("arp: send reply %d.%d.%d.%d %02x-%02x-%02x-%02x-%02x-%02x\n",
				ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3],
				netif->ethaddr[0], netif->ethaddr[1], netif->ethaddr[2],
				netif->ethaddr[3], netif->ethaddr[4], netif->ethaddr[5]);
			debug_printf ("     to %d.%d.%d.%d %02x-%02x-%02x-%02x-%02x-%02x\n",
				ah->dst_ipaddr[0], ah->dst_ipaddr[1], ah->dst_ipaddr[2], ah->dst_ipaddr[3],
				ah->dst_hwaddr[0], ah->dst_hwaddr[1], ah->dst_hwaddr[2],
				ah->dst_hwaddr[3], ah->dst_hwaddr[4], ah->dst_hwaddr[5]);
#endif
			netif->interface->output (netif, p, 0);
			return 0;

		case ARP_REPLY:
			/* ARP reply. We insert or update the ARP table.
			 * No need to check the destination IP address. */
			/* debug_printf ("arp: got reply from %d.%d.%d.%d %02x-%02x-%02x-%02x-%02x-%02x\n",
				ah->src_ipaddr[0], ah->src_ipaddr[1], ah->src_ipaddr[2], ah->src_ipaddr[3],
				ah->src_hwaddr[0], ah->src_hwaddr[1], ah->src_hwaddr[2],
				ah->src_hwaddr[3], ah->src_hwaddr[4], ah->src_hwaddr[5]); */
			arp_add_entry (netif, ah->src_ipaddr, ah->src_hwaddr);
			buf_free (p);
			return 0;
		}
	}
}
Esempio n. 6
0
static void on_msg_recv_cb(wslay_event_context_ptr ev,
                           const struct wslay_event_on_msg_recv_arg *arg,
                           void *user_data)
{
    struct transaction_t *txn = (struct transaction_t *) user_data;
    struct ws_context *ctx = (struct ws_context *) txn->ws_ctx;
    struct buf inbuf = BUF_INITIALIZER, outbuf = BUF_INITIALIZER;
    struct wslay_event_msg msgarg = { arg->opcode, NULL, 0 };
    uint8_t rsv = WSLAY_RSV_NONE;
    double cmdtime, nettime;
    const char *err_msg;
    int r, err_code = 0;

    /* Place client request into a buf */
    buf_init_ro(&inbuf, (const char *) arg->msg, arg->msg_length);

    /* Decompress request, if necessary */
    if (wslay_get_rsv1(arg->rsv)) {
        /* Add trailing 4 bytes */
        buf_appendmap(&inbuf, "\x00\x00\xff\xff", 4);

        r = zlib_decompress(txn, buf_base(&inbuf), buf_len(&inbuf));
        if (r) {
            syslog(LOG_ERR, "on_msg_recv_cb(): zlib_decompress() failed");

            err_code = WSLAY_CODE_PROTOCOL_ERROR;
            err_msg = DECOMP_FAILED_ERR;
            goto err;
        }

        buf_move(&inbuf, &txn->zbuf);
    }

    /* Log the uncompressed client request */
    buf_truncate(&ctx->log, ctx->log_tail);
    buf_appendcstr(&ctx->log, " (");
    if (txn->strm_ctx) {
        buf_printf(&ctx->log, "stream-id=%d; ",
                   http2_get_streamid(txn->strm_ctx));
    }
    buf_printf(&ctx->log, "opcode=%s; rsv=0x%x; length=%ld",
               wslay_str_opcode(arg->opcode), arg->rsv, arg->msg_length);

    switch (arg->opcode) {
    case WSLAY_CONNECTION_CLOSE:
        buf_printf(&ctx->log, "; status=%d; msg='%s'", arg->status_code,
                   buf_len(&inbuf) ? buf_cstring(&inbuf)+2 : "");
        txn->flags.conn = CONN_CLOSE;
        break;

    case WSLAY_TEXT_FRAME:
    case WSLAY_BINARY_FRAME:
        if (txn->conn->logfd != -1) {
            /* Telemetry logging */
            struct iovec iov[2];
            int niov = 0;

            assert(!buf_len(&txn->buf));
            buf_printf(&txn->buf, "<%ld<", time(NULL));  /* timestamp */
            WRITEV_ADD_TO_IOVEC(iov, niov,
                                buf_base(&txn->buf), buf_len(&txn->buf));
            WRITEV_ADD_TO_IOVEC(iov, niov, buf_base(&inbuf), buf_len(&inbuf));
            writev(txn->conn->logfd, iov, niov);
            buf_reset(&txn->buf);
        }

        /* Process the request */
        r = ctx->data_cb(&inbuf, &outbuf, &ctx->log, &ctx->cb_rock);
        if (r) {

            err_code = (r == HTTP_SERVER_ERROR ?
                        WSLAY_CODE_INTERNAL_SERVER_ERROR :
                        WSLAY_CODE_INVALID_FRAME_PAYLOAD_DATA);
            err_msg = error_message(r);
            goto err;
        }

        if (txn->conn->logfd != -1) {
            /* Telemetry logging */
            struct iovec iov[2];
            int niov = 0;

            assert(!buf_len(&txn->buf));
            buf_printf(&txn->buf, ">%ld>", time(NULL));  /* timestamp */
            WRITEV_ADD_TO_IOVEC(iov, niov,
                                buf_base(&txn->buf), buf_len(&txn->buf));
            WRITEV_ADD_TO_IOVEC(iov, niov, buf_base(&outbuf), buf_len(&outbuf));
            writev(txn->conn->logfd, iov, niov);
            buf_reset(&txn->buf);
        }

        /* Compress the server response, if supported by the client */
        if (ctx->ext & EXT_PMCE_DEFLATE) {
            r = zlib_compress(txn,
                              ctx->pmce.deflate.no_context ? COMPRESS_START : 0,
                              buf_base(&outbuf), buf_len(&outbuf));
            if (r) {
                syslog(LOG_ERR, "on_msg_recv_cb(): zlib_compress() failed");

                err_code = WSLAY_CODE_INTERNAL_SERVER_ERROR;
                err_msg = COMP_FAILED_ERR;
                goto err;
            }

            /* Trim the trailing 4 bytes */
            buf_truncate(&txn->zbuf, buf_len(&txn->zbuf) - 4);
            buf_move(&outbuf, &txn->zbuf);

            rsv |= WSLAY_RSV1_BIT;
        }

        /* Queue the server response */
        msgarg.msg = (const uint8_t *) buf_base(&outbuf);
        msgarg.msg_length = buf_len(&outbuf);
        wslay_event_queue_msg_ex(ev, &msgarg, rsv);

        /* Log the server response */
        buf_printf(&ctx->log,
                   ") => \"Success\" (opcode=%s; rsv=0x%x; length=%ld",
                   wslay_str_opcode(msgarg.opcode), rsv, msgarg.msg_length);
        break;
    }

  err:
    if (err_code) {
        size_t err_msg_len = strlen(err_msg);

        syslog(LOG_DEBUG, "wslay_event_queue_close()");
        wslay_event_queue_close(ev, err_code, (uint8_t *) err_msg, err_msg_len);

        /* Log the server response */
        buf_printf(&ctx->log,
                   ") => \"Fail\" (opcode=%s; rsv=0x%x; length=%ld"
                   "; status=%d; msg='%s'",
                   wslay_str_opcode(WSLAY_CONNECTION_CLOSE), rsv, err_msg_len,
                   err_code, err_msg);
    }

    /* Add timing stats */
    cmdtime_endtimer(&cmdtime, &nettime);
    buf_printf(&ctx->log, ") [timing: cmd=%f net=%f total=%f]",
               cmdtime, nettime, cmdtime + nettime);

    syslog(LOG_INFO, "%s", buf_cstring(&ctx->log));

    buf_free(&inbuf);
    buf_free(&outbuf);
}