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; }
/* * 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 } }
/* 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)); }
/* * 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); }
/* * 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; } } }
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); }