lsquic_qlog.c revision 9b4d33c7
1/* Copyright (c) 2017 - 2019 LiteSpeed Technologies Inc. See LICENSE. */ 2#include <stdlib.h> 3#include <stdio.h> 4#include <errno.h> 5#include <inttypes.h> 6#include <string.h> 7#include <sys/queue.h> 8#include <netinet/in.h> 9#include <arpa/inet.h> 10 11#include "lsquic.h" 12#include "lsquic_types.h" 13#include "lsquic_int_types.h" 14#include "lsquic_packet_common.h" 15#include "lsquic_packet_in.h" 16#include "lsquic_packet_out.h" 17#include "lsquic_util.h" 18#include "lsquic_qlog.h" 19 20#define LSQUIC_LOGGER_MODULE LSQLM_QLOG 21#include "lsquic_logger.h" 22 23#define LSQUIC_LOG_CONN_ID cid 24#define LCID(...) LSQ_LOG2(LSQ_LOG_DEBUG, __VA_ARGS__) 25 26#define MAX_IP_LEN INET6_ADDRSTRLEN 27#define QLOG_PACKET_RAW_SZ 64 28 29 30void 31lsquic_qlog_create_connection (lsquic_cid_t cid, 32 const struct sockaddr *local_sa, 33 const struct sockaddr *peer_sa) 34{ 35 uint32_t ip_version, srcport, dstport; 36 struct sockaddr_in *local4, *peer4; 37 struct sockaddr_in6 *local6, *peer6; 38 char srcip[MAX_IP_LEN], dstip[MAX_IP_LEN]; 39 40 if (!local_sa || !peer_sa) 41 return; 42 43 if (local_sa->sa_family == AF_INET) 44 { 45 ip_version = 4; 46 local4 = (struct sockaddr_in *)local_sa; 47 peer4 = (struct sockaddr_in *)peer_sa; 48 srcport = ntohs(local4->sin_port); 49 dstport = ntohs(peer4->sin_port); 50 inet_ntop(local4->sin_family, &local4->sin_addr, srcip, MAX_IP_LEN); 51 inet_ntop(peer4->sin_family, &peer4->sin_addr, dstip, MAX_IP_LEN); 52 } 53 else if (local_sa->sa_family == AF_INET6) 54 { 55 ip_version = 6; 56 local6 = (struct sockaddr_in6 *)local_sa; 57 peer6 = (struct sockaddr_in6 *)peer_sa; 58 srcport = ntohs(local6->sin6_port); 59 dstport = ntohs(peer6->sin6_port); 60 inet_ntop(local6->sin6_family, &local6->sin6_addr, srcip, MAX_IP_LEN); 61 inet_ntop(peer6->sin6_family, &peer6->sin6_addr, dstip, MAX_IP_LEN); 62 } 63 else 64 return; 65 66 LCID("[%" PRIu64 ",\"CONNECTIVITY\",\"NEW_CONNECTION\",\"LINE\"," 67 "{" 68 "\"ip_version\":\"%u\"," 69 "\"srcip\":\"%s\"," 70 "\"dstip\":\"%s\"," 71 "\"srcport\":\"%u\"," 72 "\"dstport\":\"%u\"" 73 "}]", 74 lsquic_time_now(), ip_version, srcip, dstip, srcport, dstport); 75} 76 77#define QLOG_FRAME_DICT_PREFIX_COMMA ",{\"frame_type\":\"" 78#define QLOG_FRAME_DICT_PREFIX "{\"frame_type\":\"" 79#define QLOG_FRAME_DICT_SUFFIX "\"}" 80#define QLOG_FRAME_LIST_PREFIX ",\"frames\":[" 81#define QLOG_FRAME_LIST_SUFFIX "]" 82#define QLOG_FRAME_LIST_MAX \ 83 sizeof(QLOG_FRAME_LIST_PREFIX) + \ 84 sizeof(QLOG_FRAME_LIST_SUFFIX) + \ 85 lsquic_frame_types_str_sz + \ 86 (N_QUIC_FRAMES * \ 87 (sizeof(QLOG_FRAME_DICT_PREFIX_COMMA) + \ 88 sizeof(QLOG_FRAME_DICT_SUFFIX))) 89 90void 91lsquic_qlog_packet_rx (lsquic_cid_t cid, 92 const struct lsquic_packet_in *packet_in, 93 const unsigned char *packet_in_data, 94 size_t packet_in_size) 95{ 96 int i, cur = 0, first = 0, ret = 0; 97 size_t raw_bytes_written; 98 char data[QLOG_PACKET_RAW_SZ]; 99 char frame_list[QLOG_FRAME_LIST_MAX + 1]; 100 101 if (!packet_in || !packet_in_data) 102 return; 103 104 frame_list[cur] = '\0'; 105 if (packet_in->pi_frame_types) 106 { 107 cur = sprintf(frame_list, "%s", QLOG_FRAME_LIST_PREFIX); 108 for (i = 0; i < N_QUIC_FRAMES; i++) 109 if (packet_in->pi_frame_types & (1 << i)) 110 { 111 ret = snprintf(frame_list + cur, 112 QLOG_FRAME_LIST_MAX - cur, 113 /* prefix + FRAME_NAME + suffix */ 114 "%s%s%s", 115 /* skip comma in prefix if first frame */ 116 (first++ ? 117 QLOG_FRAME_DICT_PREFIX_COMMA : 118 QLOG_FRAME_DICT_PREFIX), 119 QUIC_FRAME_NAME(i), 120 QLOG_FRAME_DICT_SUFFIX); 121 if ((unsigned)ret > QLOG_FRAME_LIST_MAX - cur) 122 break; 123 cur += ret; 124 } 125 if ((unsigned)cur <= QLOG_FRAME_LIST_MAX) 126 sprintf(frame_list + cur, "%s", QLOG_FRAME_LIST_SUFFIX); 127 } 128 129 raw_bytes_written = lsquic_hex_encode(packet_in_data, packet_in_size, 130 data, QLOG_PACKET_RAW_SZ); 131 132 LCID("[%" PRIu64 ",\"TRANSPORT\",\"PACKET_RX\",\"LINE\"," 133 "{" 134 "\"raw\":\"%s%s\"," 135 "\"header\":{" 136 "\"type\":\"%s\"," 137 "\"payload_length\":\"%d\"," 138 "\"packet_number\":\"%" PRIu64 "\"" 139 "}%s" 140 "}]", 141 packet_in->pi_received, 142 data, (raw_bytes_written < packet_in_size) ? "..." : "", 143 lsquic_hety2str[packet_in->pi_header_type], 144 packet_in->pi_data_sz, 145 packet_in->pi_packno, 146 frame_list); 147} 148 149 150void 151lsquic_qlog_hsk_completed (lsquic_cid_t cid) 152{ 153 LCID("[%" PRIu64 ",\"CONNECTIVITY\",\"HANDSHAKE\",\"PACKET_RX\"," 154 "{\"status\":\"complete\"}]", lsquic_time_now()); 155} 156 157 158void 159lsquic_qlog_zero_rtt (lsquic_cid_t cid) 160{ 161 LCID("[%" PRIu64 ",\"RECOVERY\",\"RTT_UPDATE\",\"PACKET_RX\"," 162 "{\"zero_rtt\":\"successful\"}]", lsquic_time_now()); 163} 164 165 166void 167lsquic_qlog_check_certs (lsquic_cid_t cid, const lsquic_str_t **certs, 168 size_t count) 169{ 170 size_t i; 171 size_t buf_sz = 0; 172 char *buf = NULL; 173 char *new_buf; 174 175 for (i = 0; i < count; i++) 176 { 177 if (buf_sz < (lsquic_str_len(certs[i]) * 2) + 1) 178 { 179 buf_sz = (lsquic_str_len(certs[i]) * 2) + 1; 180 new_buf = realloc(buf, buf_sz); 181 if (!new_buf) 182 break; 183 buf = new_buf; 184 } 185 lsquic_hex_encode(lsquic_str_cstr(certs[i]), lsquic_str_len(certs[i]), 186 buf, buf_sz); 187 LCID("[%" PRIu64 ",\"SECURITY\",\"CHECK_CERT\",\"CERTLOG\"," 188 "{\"certificate\":\"%s\"}]", lsquic_time_now(), buf); 189 } 190 if (buf) 191 free(buf); 192} 193 194 195void 196lsquic_qlog_version_negotiation (lsquic_cid_t cid, 197 const char *action, const char *ver) 198{ 199 char *trig; 200 201 if (!action || !ver) 202 return; 203 if (strcmp(action, "proposed") == 0) 204 trig = "LINE"; 205 else if (strcmp(action, "agreed") == 0) 206 trig = "PACKET_RX"; 207 else 208 return; 209 LCID("[%" PRIu64 ",\"CONNECTIVITY\",\"VERNEG\",\"%s\"," 210 "{\"%s_version\":\"%s\"}]", lsquic_time_now(), trig, action, ver); 211} 212