static enum proto_parse_status cursor_read_tns_hdr(struct cursor *cursor, size_t *out_len, unsigned *out_type) { /* TNS PDU have a header consisting of (in network byte order) : * - a 2 bytes length * - a 2 bytes checksum * - a one byte type * - a one byte 0 * - a 2 bytes header checksum (or 0) */ SLOG(LOG_DEBUG, "Reading a TNS PDU"); CHECK_LEN(cursor, 8, 0); size_t len = cursor_read_u16n(cursor); if (len < 8) return PROTO_PARSE_ERR; len -= 8; SLOG(LOG_DEBUG, "TNS PDU len == %zu", len); // skip packet checksum (2 bytes) cursor_drop(cursor, 2); unsigned type = cursor_read_u8(cursor); // Skip Reserved byte and header checksum (1 + 2 bytes) cursor_drop(cursor, 3); if (type > TNS_TYPE_MAX) return PROTO_PARSE_ERR; // Check we have the msg payload CHECK_LEN(cursor, len, 8); if (out_len) *out_len = len; if (out_type) *out_type = type; return PROTO_OK; }
/* Read a message header, return type and msg length, and advance the cursor to the msg payload. * if type is NULL that means no type are read from the cursor. * return PROTO_TOO_SHORT if the msg content is not available. */ static enum proto_parse_status cursor_read_msg(struct cursor *cursor, uint8_t *type, size_t *len_) { SLOG(LOG_DEBUG, "Reading new message"); unsigned rollback = 0; if (type) { // read type first CHECK_LEN(cursor, 1, rollback); *type = cursor_read_u8(cursor); rollback++; SLOG(LOG_DEBUG, "... of type %u ('%c')", (unsigned)*type, *type); } // read length CHECK_LEN(cursor, 4, rollback); size_t len = cursor_read_u32n(cursor); rollback += 4; if (len < 4) return PROTO_PARSE_ERR; // as length includes itself len -= 4; SLOG(LOG_DEBUG, "... of length %zu", len); if (len_) *len_ = len; // read payload CHECK_LEN(cursor, len, rollback); return PROTO_OK; }
static int anoubisd_msg_upgrade_size(const char *buf, int buflen) { struct anoubisd_msg_upgrade *msg; DECLARE_SIZE(); CAST(msg, buf, buflen); SHIFT_FIELD(msg, chunk, buf, buflen); if (msg->upgradetype != ANOUBISD_UPGRADE_NOTIFY) CHECK_LEN(msg->chunksize, buflen); switch(msg->upgradetype) { case ANOUBISD_UPGRADE_OK: if (msg->chunksize != 1) return -1; ADD_SIZE(msg->chunksize); break; case ANOUBISD_UPGRADE_NOTIFY: /* * chunksize is the number of upgraded files. No data in * in chunk. */ break; case ANOUBISD_UPGRADE_CHUNK: if (msg->chunksize) STRINGS(buf, buflen); break; default: if (msg->chunksize) return -1; } RETURN_SIZE(); }
/* TNS PDU have a header consisting of (in network byte order) : * * | 2 bytes | 2 bytes | 1 byte | 1 byte | 2 bytes | * | Length | Checksum | Type | a zero | Header checksum | */ static enum proto_parse_status cursor_read_tns_hdr(struct cursor *cursor, size_t *out_len, unsigned *out_type, size_t wire_len) { SLOG(LOG_DEBUG, "Reading a TNS PDU"); CHECK_LEN(cursor, 8, 0); size_t len = cursor_read_u16n(cursor); if (len < 8 || len < wire_len) return PROTO_PARSE_ERR; len -= 8; SLOG(LOG_DEBUG, "TNS PDU len == %zu", len); // Checksum should be 0 uint_least16_t checksum = cursor_read_u16n(cursor); if (checksum > 0) { SLOG(LOG_DEBUG, "Tns checksum should be 0, got %u", checksum); return PROTO_PARSE_ERR; } unsigned type = cursor_read_u8(cursor); if (type >= TNS_TYPE_MAX) { SLOG(LOG_DEBUG, "Tns type invalid, sould be < %u, got %u", TNS_TYPE_MAX, type); return PROTO_PARSE_ERR; } // reserved byte and header checksum should be 0 uint_least32_t head_checksum =cursor_read_u24(cursor); if (head_checksum > 0) { SLOG(LOG_DEBUG, "Reserved byte and checksum should be 0, got %u", head_checksum); return PROTO_PARSE_ERR; } if (out_len) *out_len = len; if (out_type) *out_type = type; // Check we have the msg payload CHECK(len); return PROTO_OK; }
static int anoubisd_sfscache_invalidate_size(const char *buf, int buflen) { struct anoubisd_sfscache_invalidate *msg; DECLARE_SIZE(); CAST(msg, buf, buflen); SHIFT_FIELD(msg, payload, buf, buflen); CHECK_LEN(msg->plen, buflen); CHECK_STRING(buf, msg->plen); SHIFT_CNT(msg->plen, buf, buflen); if (msg->keylen) { CHECK_LEN(msg->keylen, buflen); STRINGS(buf, buflen); } RETURN_SIZE(); }
static int anoubisd_msg_polreply_size(const char *buf, int buflen) { DECLARE_SIZE(); struct anoubisd_msg_polreply *reply; CAST(reply, buf, buflen); SHIFT_FIELD(reply, data, buf, buflen); CHECK_LEN(reply->len, buflen); ADD_SIZE(reply->len); RETURN_SIZE(); }
static inline void sniff_loop_ip(session_t *s, int len, const u_char *packet) { const struct iphdr *ip; int size_ip; CHECK_LEN(sizeof(struct iphdr)) ip = (struct iphdr *) (packet); size_ip = ip->ip_hl*4; if (size_ip < 20) { debug_error("sniff_loop_ip() * Invalid IP header length: %u bytes\n", size_ip); return; } if (ip->ip_p == IPPROTO_TCP) sniff_loop_tcp(s, len - size_ip, packet + size_ip, ip, size_ip); else if (ip->ip_p == IPPROTO_UDP) sniff_loop_udp(s, len - size_ip, packet + size_ip, ip); else if (ip->ip_p == IPPROTO_ICMP) { /* ICMP, stub only */ const struct icmphdr *icmp; CHECK_LEN(size_ip + sizeof(struct icmphdr)); icmp = (struct icmphdr *) (packet + size_ip); debug_function("sniff_loop_ip() IP/ICMP %15s <==> %15s TYPE: %d CODE: %d CHKSUM: %d\n", _inet_ntoa(ip->ip_src), /* src ip */ _inet_ntoa(ip->ip_dst), /* dest ip */ icmp->icmp_type, icmp->icmp_code, icmp->icmp_cksum); /* XXX */ } else { /* other, implement if u want to || die. */ debug_error("sniff_loop_ip() IP/0x%x %15s <==> %15s\n", ip->ip_p, /* protocol */ _inet_ntoa(ip->ip_src), /* src ip */ _inet_ntoa(ip->ip_dst)); /* dest ip */ } }
static inline void sniff_loop_udp(session_t *s, int len, const u_char *packet, const struct iphdr *ip) { #define RIVCHAT_PACKET_LEN 328 static const char rivchat_magic[11] = { 'R', 'i', 'v', 'C', 'h', 'a', 't' /* here NULs */}; /* RivChat\0\0\0\0 */ /* XXX here, make some struct with known UDP services, and demangler-function */ const struct udphdr *udp; connection_t *hdr; const char *payload; int size_payload; /* XXX, it's enough? */ /* code copied from: http://gpsbots.com/tutorials/sniff_packets.php */ CHECK_LEN(sizeof(struct udphdr)); udp = (struct udphdr *) (packet); hdr = sniff_udp_get(ip, udp); payload = (char *) (packet + sizeof(struct udphdr)); size_payload = g_ntohs(udp->th_len)-sizeof(struct udphdr); CHECK_LEN(sizeof(struct udphdr) + size_payload); debug_error("sniff_loop_udp() IP/UDP %15s:%5d <==> %15s:%5d\n", _inet_ntoa(hdr->srcip), /* src ip */ hdr->srcport, /* src port */ _inet_ntoa(hdr->dstip), /* dest ip */ hdr->dstport); /* dest port */ if (size_payload == RIVCHAT_PACKET_LEN && !memcmp(payload, rivchat_magic, sizeof(rivchat_magic))) { /* RIVCHAT [check based on header (11b), ~100% hit] */ sniff_rivchat(s, hdr, (rivchat_packet *) payload, size_payload); } else if (hdr->srcport == 53 || hdr->dstport == 53) { /* DNS [check based on port, ~80% hit] */ sniff_dns(s, hdr, (DNS_HEADER *) payload, size_payload); } else { /* OTHER PROTOs, feel free */ debug_error("NOT RIVCHAT/ NOT DNS:\n"); tcp_print_payload((u_char *) payload, size_payload); } }
// | 1 byte | 1 byte | 2 bytes | 4 bytes | 4 bytes | 4 bytes | // | SMID (0x53) | Flag | SID | Length | Seq num | Window | static enum proto_parse_status tds_parse_smp_header(struct cursor *cursor, struct smp_header *out_header) { # define SMP_PKT_HDR_LEN 0x10 # define SMP_SMID 0x53 if (cursor_peek_u8(cursor, 0) == SMP_SMID) { CHECK_LEN(cursor, SMP_PKT_HDR_LEN, 0); cursor_drop(cursor, 1); out_header->flags = cursor_read_u8(cursor); out_header->sid = cursor_read_u16le(cursor); out_header->length = cursor_read_u32le(cursor); out_header->seq_num = cursor_read_u32le(cursor); out_header->window = cursor_read_u32le(cursor); } return PROTO_OK; }
/* * Return the size of an anoubisd_msg_polrequest message. */ static int anoubisd_msg_polrequest_size(const char *buf, int buflen) { DECLARE_SIZE(); struct anoubisd_msg_polrequest *req; CAST(req, buf, buflen); SHIFT_FIELD(req, data, buf, buflen); CHECK_LEN(req->len, buflen); ADD_SIZE(req->len); if (verify_polrequest(buf, req->len, req->flags) < 0) return -1; RETURN_SIZE(); }
/* * Size of an eventdev_hdr. */ int eventdev_hdr_size(const char *buf, int buflen) { struct eventdev_hdr *hdr; DECLARE_SIZE(); CAST(hdr, buf, buflen); CHECK_LEN(hdr->msg_size, buflen); CHECK_SIZE(hdr->msg_size); SHIFT_CNT(sizeof(*hdr), buf, buflen); switch(hdr->msg_source) { VARIANT(ANOUBIS_SOURCE_ALF, alf_event, buf, buflen); VARIANT(ANOUBIS_SOURCE_SANDBOX, sfs_open_message, buf, buflen); VARIANT(ANOUBIS_SOURCE_SFS, sfs_open_message, buf, buflen); VARIANT(ANOUBIS_SOURCE_SFSEXEC, sfs_open_message, buf, buflen); #ifdef ANOUBIS_SOURCE_SFSPATH VARIANT(ANOUBIS_SOURCE_SFSPATH, sfs_path_message, buf, buflen); #endif VARIANT(ANOUBIS_SOURCE_PROCESS, ac_process_message, buf, buflen); VARIANT(ANOUBIS_SOURCE_STAT, anoubis_stat_message, buf, buflen); VARIANT(ANOUBIS_SOURCE_IPC, ac_ipc_message, buf, buflen); VARIANT(ANOUBIS_SOURCE_PLAYGROUND, pg_open_message, buf, buflen); VARIANT(ANOUBIS_SOURCE_PLAYGROUNDPROC, pg_proc_message, buf, buflen); VARIANT(ANOUBIS_SOURCE_PLAYGROUNDFILE, pg_file_message, buf, buflen); default: return -2; } if (__local_size > hdr->msg_size) { if (__local_size <= 0) return -3; else return -(__local_size); } if (__local_size + 8 < hdr->msg_size) { if (__local_size <= 0) return -4; else return -(__local_size + 100000); } /* * NOTE: Do NOT return the calculated size here because this * NOTE: is usually used within a container and that container * NOTE: must treat the padding space as part of the message. */ return hdr->msg_size; }
static enum proto_parse_status tds_parse_header(struct cursor *cursor, struct tds_header *out_header, bool *unknown_token) { # define TDS_PKT_HDR_LEN 8 CHECK_LEN(cursor, TDS_PKT_HDR_LEN, 0); struct tds_header header; header.type = cursor_read_u8(cursor); header.status = cursor_read_u8(cursor); header.len = cursor_read_u16n(cursor); header.channel = cursor_read_u16n(cursor); header.pkt_number = cursor_read_u8(cursor); header.window = cursor_read_u8(cursor); SLOG(LOG_DEBUG, "Reading new TDS packet %s", tds_header_2_str(&header)); // sanity check if (header.len < TDS_PKT_HDR_LEN) return PROTO_PARSE_ERR; switch (header.type) { case TDS_PKT_TYPE_SQL_BATCH: case TDS_PKT_TYPE_LOGIN: case TDS_PKT_TYPE_RPC: case TDS_PKT_TYPE_RESULT: case TDS_PKT_TYPE_ATTENTION: case TDS_PKT_TYPE_BULK_LOAD: case TDS_PKT_TYPE_MANAGER_REQ: case TDS_PKT_TYPE_TDS7_LOGIN: case TDS_PKT_TYPE_SSPI: case TDS_PKT_TYPE_PRELOGIN: break; default: SLOG(LOG_DEBUG, "Unknown tds type %u", header.type); if (unknown_token) *unknown_token = true; return PROTO_PARSE_ERR; } if (header.window != 0) { SLOG(LOG_DEBUG, "Window is %"PRIu8" instead of 0", header.window); return PROTO_PARSE_ERR; } size_t data_left = header.len - TDS_PKT_HDR_LEN; if ((data_left > 0) != tds_packet_has_data(header.type)) { SLOG(LOG_DEBUG, "This TDS packet of type %s has %zu bytes of data, but should%s have data", tds_packet_type_2_str(header.type), data_left, tds_packet_has_data(header.type) ? "":" not"); return PROTO_PARSE_ERR; } if (out_header) *out_header = header; return PROTO_OK; }
enum proto_parse_status cursor_read_string(struct cursor *cursor, char **out_str, size_t max_len) { char *str = tempstr(); unsigned len; if (max_len > TEMPSTR_SIZE-1) max_len = TEMPSTR_SIZE-1; for (len = 0; len < max_len; len ++) { CHECK_LEN(cursor, 1, len); uint8_t c = cursor_read_u8(cursor); if (c == '\0') break; str[len] = c; } if (len == max_len) { cursor_rollback(cursor, len); return PROTO_TOO_SHORT; } str[len] = '\0'; SLOG(LOG_DEBUG, "Reading string '%s' of size %u", str, len); if (out_str) *out_str = str; return PROTO_OK; }
/* {{{ get_next_char */ inline static unsigned int get_next_char(enum entity_charset charset, unsigned char * str, int str_len, int * newpos, unsigned char * mbseq, int * mbseqlen, int *status) { int pos = *newpos; int mbpos = 0; int mbspace = *mbseqlen; unsigned int this_char = 0; unsigned char next_char; *status = SUCCESS; if (mbspace <= 0) { *mbseqlen = 0; CHECK_LEN(pos, 1); *newpos = pos + 1; return str[pos]; } switch (charset) { case cs_utf_8: { unsigned char c; CHECK_LEN(pos, 1); c = str[pos]; if (c < 0x80) { MB_WRITE(c); this_char = c; pos++; } else if (c < 0xc0) { MB_FAILURE(pos); } else if (c < 0xe0) { CHECK_LEN(pos, 2); if (str[pos + 1] < 0x80 || str[pos + 1] > 0xbf) { MB_FAILURE(pos); } this_char = ((c & 0x1f) << 6) | (str[pos + 1] & 0x3f); if (this_char < 0x80) { MB_FAILURE(pos); } MB_WRITE((unsigned char)c); MB_WRITE((unsigned char)str[pos + 1]); pos += 2; } else if (c < 0xf0) { CHECK_LEN(pos, 3); if (str[pos + 1] < 0x80 || str[pos + 1] > 0xbf) { MB_FAILURE(pos); } if (str[pos + 2] < 0x80 || str[pos + 2] > 0xbf) { MB_FAILURE(pos); } this_char = ((c & 0x0f) << 12) | ((str[pos + 1] & 0x3f) << 6) | (str[pos + 2] & 0x3f); if (this_char < 0x800) { MB_FAILURE(pos); } else if (this_char >= 0xd800 && this_char <= 0xdfff) { MB_FAILURE(pos); } MB_WRITE((unsigned char)c); MB_WRITE((unsigned char)str[pos + 1]); MB_WRITE((unsigned char)str[pos + 2]); pos += 3; } else if (c < 0xf8) { CHECK_LEN(pos, 4); if (str[pos + 1] < 0x80 || str[pos + 1] > 0xbf) { MB_FAILURE(pos); } if (str[pos + 2] < 0x80 || str[pos + 2] > 0xbf) { MB_FAILURE(pos); } if (str[pos + 3] < 0x80 || str[pos + 3] > 0xbf) { MB_FAILURE(pos); } this_char = ((c & 0x07) << 18) | ((str[pos + 1] & 0x3f) << 12) | ((str[pos + 2] & 0x3f) << 6) | (str[pos + 3] & 0x3f); if (this_char < 0x10000) { MB_FAILURE(pos); } MB_WRITE((unsigned char)c); MB_WRITE((unsigned char)str[pos + 1]); MB_WRITE((unsigned char)str[pos + 2]); MB_WRITE((unsigned char)str[pos + 3]); pos += 4; } else { MB_FAILURE(pos); } } break; case cs_big5: case cs_gb2312: case cs_big5hkscs: { CHECK_LEN(pos, 1); this_char = str[pos++]; /* check if this is the first of a 2-byte sequence */ if (this_char >= 0x81 && this_char <= 0xfe) { /* peek at the next char */ CHECK_LEN(pos, 1); next_char = str[pos++]; if ((next_char >= 0x40 && next_char <= 0x7e) || (next_char >= 0xa1 && next_char <= 0xfe)) { /* yes, this a wide char */ MB_WRITE(this_char); MB_WRITE(next_char); this_char = (this_char << 8) | next_char; } else { MB_FAILURE(pos); } } else { MB_WRITE(this_char); } } break; case cs_sjis: { CHECK_LEN(pos, 1); this_char = str[pos++]; /* check if this is the first of a 2-byte sequence */ if ((this_char >= 0x81 && this_char <= 0x9f) || (this_char >= 0xe0 && this_char <= 0xfc)) { /* peek at the next char */ CHECK_LEN(pos, 1); next_char = str[pos++]; if ((next_char >= 0x40 && next_char <= 0x7e) || (next_char >= 0x80 && next_char <= 0xfc)) { /* yes, this a wide char */ MB_WRITE(this_char); MB_WRITE(next_char); this_char = (this_char << 8) | next_char; } else { MB_FAILURE(pos); } } else { MB_WRITE(this_char); } break; } case cs_eucjp: { CHECK_LEN(pos, 1); this_char = str[pos++]; /* check if this is the first of a multi-byte sequence */ if (this_char >= 0xa1 && this_char <= 0xfe) { /* peek at the next char */ CHECK_LEN(pos, 1); next_char = str[pos++]; if (next_char >= 0xa1 && next_char <= 0xfe) { /* yes, this a jis kanji char */ MB_WRITE(this_char); MB_WRITE(next_char); this_char = (this_char << 8) | next_char; } else { MB_FAILURE(pos); } } else if (this_char == 0x8e) { /* peek at the next char */ CHECK_LEN(pos, 1); next_char = str[pos++]; if (next_char >= 0xa1 && next_char <= 0xdf) { /* JIS X 0201 kana */ MB_WRITE(this_char); MB_WRITE(next_char); this_char = (this_char << 8) | next_char; } else { MB_FAILURE(pos); } } else if (this_char == 0x8f) { /* peek at the next two char */ unsigned char next2_char; CHECK_LEN(pos, 2); next_char = str[pos]; next2_char = str[pos + 1]; pos += 2; if ((next_char >= 0xa1 && next_char <= 0xfe) && (next2_char >= 0xa1 && next2_char <= 0xfe)) { /* JIS X 0212 hojo-kanji */ MB_WRITE(this_char); MB_WRITE(next_char); MB_WRITE(next2_char); this_char = (this_char << 16) | (next_char << 8) | next2_char; } else { MB_FAILURE(pos); } } else { MB_WRITE(this_char); } break; } default: /* single-byte charsets */ CHECK_LEN(pos, 1); this_char = str[pos++]; MB_WRITE(this_char); break; } MB_RETURN; }
U_DRAFT uint32_t U_EXPORT2 ubiditransform_transform(UBiDiTransform *pBiDiTransform, const UChar *src, int32_t srcLength, UChar *dest, int32_t destSize, UBiDiLevel inParaLevel, UBiDiOrder inOrder, UBiDiLevel outParaLevel, UBiDiOrder outOrder, UBiDiMirroring doMirroring, uint32_t shapingOptions, UErrorCode *pErrorCode) { uint32_t destLength = 0; UBool textChanged = FALSE; const UBiDiTransform *pOrigTransform = pBiDiTransform; const UBiDiAction *action = NULL; if (U_FAILURE(*pErrorCode)) { return 0; } if (src == NULL || dest == NULL) { *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; return 0; } CHECK_LEN(src, srcLength, pErrorCode); CHECK_LEN(dest, destSize, pErrorCode); if (pBiDiTransform == NULL) { pBiDiTransform = ubiditransform_open(pErrorCode); if (U_FAILURE(*pErrorCode)) { return 0; } } /* Current limitation: in multiple paragraphs will be resolved according to the 1st paragraph */ resolveBaseDirection(src, srcLength, &inParaLevel, &outParaLevel); pBiDiTransform->pActiveScheme = findMatchingScheme(inParaLevel, outParaLevel, inOrder, outOrder); if (pBiDiTransform->pActiveScheme == NULL) { goto cleanup; } pBiDiTransform->reorderingOptions = doMirroring ? UBIDI_DO_MIRRORING : UBIDI_REORDER_DEFAULT; /* Ignore TEXT_DIRECTION_* flags, as we apply our own depending on the text scheme at the time shaping is invoked. */ shapingOptions &= ~U_SHAPE_TEXT_DIRECTION_MASK; pBiDiTransform->digits = shapingOptions & ~U_SHAPE_LETTERS_MASK; pBiDiTransform->letters = shapingOptions & ~U_SHAPE_DIGITS_MASK; updateSrc(pBiDiTransform, src, srcLength, destSize > srcLength ? destSize : srcLength, pErrorCode); if (U_FAILURE(*pErrorCode)) { goto cleanup; } if (pBiDiTransform->pBidi == NULL) { pBiDiTransform->pBidi = ubidi_openSized(0, 0, pErrorCode); if (U_FAILURE(*pErrorCode)) { goto cleanup; } } pBiDiTransform->dest = dest; pBiDiTransform->destSize = destSize; pBiDiTransform->pDestLength = &destLength; /* Checking for U_SUCCESS() within the loop to bail out on first failure. */ for (action = pBiDiTransform->pActiveScheme->actions; *action && U_SUCCESS(*pErrorCode); action++) { if ((*action)(pBiDiTransform, pErrorCode)) { if (action + 1) { updateSrc(pBiDiTransform, pBiDiTransform->dest, *pBiDiTransform->pDestLength, *pBiDiTransform->pDestLength, pErrorCode); } textChanged = TRUE; } } ubidi_setInverse(pBiDiTransform->pBidi, FALSE); if (!textChanged && U_SUCCESS(*pErrorCode)) { /* Text was not changed - just copy src to dest */ if (destSize < srcLength) { *pErrorCode = U_BUFFER_OVERFLOW_ERROR; } else { u_strncpy(dest, src, srcLength); destLength = srcLength; } } cleanup: if (pOrigTransform != pBiDiTransform) { ubiditransform_close(pBiDiTransform); } else { pBiDiTransform->dest = NULL; pBiDiTransform->pDestLength = NULL; pBiDiTransform->srcLength = 0; pBiDiTransform->destSize = 0; } return U_FAILURE(*pErrorCode) ? 0 : destLength; }
int read_thrift(char *ptr, int len, ThriftMessage *tm) { int off; int x; int fieldId; char fieldType; memset(tm, 0, sizeof(*tm)); off = 0; READ_I32(ptr, off, len, x); // ASSERT version stuff tm->messageType = x & 0xff; READ_STRING(ptr, off, len, tm->name_len, tm->name_ptr); READ_I32(ptr, off, len, tm->seqid); while(1) { READ_I8(ptr, off, len, fieldType); if(fieldType == T_STOP) break; READ_I16(ptr, off, len, fieldId); if(fieldId > MAX_FIELD_ID || fieldId < 0) { printf("Ignoring field with out of range id, id = %d, max = %d", MAX_FIELD_ID, fieldId); fieldId = -1; } if(fieldId >= 0) { tm->fields[fieldId].present = 1; tm->fields[fieldId].fieldType = fieldType; } switch(fieldType) { case T_STOP: break; case T_VOID: continue; case T_BOOL: // case T_BYTE: would be a dupe case T_I08: CHECK_LEN(off, len, 1); if(fieldId >= 0) { tm->fields[fieldId].val_len = 1; tm->fields[fieldId].val_ptr = ptr + off; tm->fields[fieldId].val_val = (int) ptr[off]; } off += 1; break; case T_I16: CHECK_LEN(off, len, 2); if(fieldId >= 0) { short s; tm->fields[fieldId].val_len = 2; tm->fields[fieldId].val_ptr = ptr + off; memcpy(&s, ptr + off, 2); tm->fields[fieldId].val_val = (int) ntohs(s); } off += 2; break; case T_I32: CHECK_LEN(off, len, 4); if(fieldId >= 0) { int i; tm->fields[fieldId].val_len = 4; tm->fields[fieldId].val_ptr = ptr + off; memcpy(&i, ptr + off, 4); tm->fields[fieldId].val_val = ntohl(i); } off += 4; break; case T_U64: case T_I64: case T_DOUBLE: CHECK_LEN(off, len, 8); if(fieldId >= 0) { tm->fields[fieldId].val_len = 8; tm->fields[fieldId].val_ptr = ptr + off; } off += 8; break; // Treat all of these as just length-delimited case T_STRING: // case T_UTF7: duplicate case T_STRUCT: case T_MAP: case T_SET: case T_LIST: case T_UTF8: case T_UTF16: if(fieldId >= 0) { READ_STRING(ptr, off, len, tm->fields[fieldId].val_len, tm->fields[fieldId].val_ptr); } else { char *p_ign; int l_ign; READ_STRING(ptr, off, len, l_ign, p_ign); } break; } } return off; too_short: return 0; }
/* {{{ get_next_char */ static inline unsigned int get_next_char( enum entity_charset charset, const unsigned char *str, size_t str_len, size_t *cursor, int *status) { size_t pos = *cursor; unsigned int this_char = 0; *status = SUCCESS; assert(pos <= str_len); if (!CHECK_LEN(pos, 1)) MB_FAILURE(pos, 1); switch (charset) { case cs_utf_8: { /* We'll follow strategy 2. from section 3.6.1 of UTR #36: * "In a reported illegal byte sequence, do not include any * non-initial byte that encodes a valid character or is a leading * byte for a valid sequence." */ unsigned char c; c = str[pos]; if (c < 0x80) { this_char = c; pos++; } else if (c < 0xc2) { MB_FAILURE(pos, 1); } else if (c < 0xe0) { if (!CHECK_LEN(pos, 2)) MB_FAILURE(pos, 1); if (!utf8_trail(str[pos + 1])) { MB_FAILURE(pos, utf8_lead(str[pos + 1]) ? 1 : 2); } this_char = ((c & 0x1f) << 6) | (str[pos + 1] & 0x3f); if (this_char < 0x80) { /* non-shortest form */ MB_FAILURE(pos, 2); } pos += 2; } else if (c < 0xf0) { size_t avail = str_len - pos; if (avail < 3 || !utf8_trail(str[pos + 1]) || !utf8_trail(str[pos + 2])) { if (avail < 2 || utf8_lead(str[pos + 1])) MB_FAILURE(pos, 1); else if (avail < 3 || utf8_lead(str[pos + 2])) MB_FAILURE(pos, 2); else MB_FAILURE(pos, 3); } this_char = ((c & 0x0f) << 12) | ((str[pos + 1] & 0x3f) << 6) | (str[pos + 2] & 0x3f); if (this_char < 0x800) { /* non-shortest form */ MB_FAILURE(pos, 3); } else if (this_char >= 0xd800 && this_char <= 0xdfff) { /* surrogate */ MB_FAILURE(pos, 3); } pos += 3; } else if (c < 0xf5) { size_t avail = str_len - pos; if (avail < 4 || !utf8_trail(str[pos + 1]) || !utf8_trail(str[pos + 2]) || !utf8_trail(str[pos + 3])) { if (avail < 2 || utf8_lead(str[pos + 1])) MB_FAILURE(pos, 1); else if (avail < 3 || utf8_lead(str[pos + 2])) MB_FAILURE(pos, 2); else if (avail < 4 || utf8_lead(str[pos + 3])) MB_FAILURE(pos, 3); else MB_FAILURE(pos, 4); } this_char = ((c & 0x07) << 18) | ((str[pos + 1] & 0x3f) << 12) | ((str[pos + 2] & 0x3f) << 6) | (str[pos + 3] & 0x3f); if (this_char < 0x10000 || this_char > 0x10FFFF) { /* non-shortest form or outside range */ MB_FAILURE(pos, 4); } pos += 4; } else { MB_FAILURE(pos, 1); } } break; case cs_big5: /* reference http://demo.icu-project.org/icu-bin/convexp?conv=big5 */ { unsigned char c = str[pos]; if (c >= 0x81 && c <= 0xFE) { unsigned char next; if (!CHECK_LEN(pos, 2)) MB_FAILURE(pos, 1); next = str[pos + 1]; if ((next >= 0x40 && next <= 0x7E) || (next >= 0xA1 && next <= 0xFE)) { this_char = (c << 8) | next; } else { MB_FAILURE(pos, 1); } pos += 2; } else { this_char = c; pos += 1; } } break; case cs_big5hkscs: { unsigned char c = str[pos]; if (c >= 0x81 && c <= 0xFE) { unsigned char next; if (!CHECK_LEN(pos, 2)) MB_FAILURE(pos, 1); next = str[pos + 1]; if ((next >= 0x40 && next <= 0x7E) || (next >= 0xA1 && next <= 0xFE)) { this_char = (c << 8) | next; } else if (next != 0x80 && next != 0xFF) { MB_FAILURE(pos, 1); } else { MB_FAILURE(pos, 2); } pos += 2; } else { this_char = c; pos += 1; } } break; case cs_gb2312: /* EUC-CN */ { unsigned char c = str[pos]; if (c >= 0xA1 && c <= 0xFE) { unsigned char next; if (!CHECK_LEN(pos, 2)) MB_FAILURE(pos, 1); next = str[pos + 1]; if (gb2312_trail(next)) { this_char = (c << 8) | next; } else if (gb2312_lead(next)) { MB_FAILURE(pos, 1); } else { MB_FAILURE(pos, 2); } pos += 2; } else if (gb2312_lead(c)) { this_char = c; pos += 1; } else { MB_FAILURE(pos, 1); } } break; case cs_sjis: { unsigned char c = str[pos]; if ((c >= 0x81 && c <= 0x9F) || (c >= 0xE0 && c <= 0xFC)) { unsigned char next; if (!CHECK_LEN(pos, 2)) MB_FAILURE(pos, 1); next = str[pos + 1]; if (sjis_trail(next)) { this_char = (c << 8) | next; } else if (sjis_lead(next)) { MB_FAILURE(pos, 1); } else { MB_FAILURE(pos, 2); } pos += 2; } else if (c < 0x80 || (c >= 0xA1 && c <= 0xDF)) { this_char = c; pos += 1; } else { MB_FAILURE(pos, 1); } } break; case cs_eucjp: { unsigned char c = str[pos]; if (c >= 0xA1 && c <= 0xFE) { unsigned next; if (!CHECK_LEN(pos, 2)) MB_FAILURE(pos, 1); next = str[pos + 1]; if (next >= 0xA1 && next <= 0xFE) { /* this a jis kanji char */ this_char = (c << 8) | next; } else { MB_FAILURE(pos, (next != 0xA0 && next != 0xFF) ? 1 : 2); } pos += 2; } else if (c == 0x8E) { unsigned next; if (!CHECK_LEN(pos, 2)) MB_FAILURE(pos, 1); next = str[pos + 1]; if (next >= 0xA1 && next <= 0xDF) { /* JIS X 0201 kana */ this_char = (c << 8) | next; } else { MB_FAILURE(pos, (next != 0xA0 && next != 0xFF) ? 1 : 2); } pos += 2; } else if (c == 0x8F) { size_t avail = str_len - pos; if (avail < 3 || !(str[pos + 1] >= 0xA1 && str[pos + 1] <= 0xFE) || !(str[pos + 2] >= 0xA1 && str[pos + 2] <= 0xFE)) { if (avail < 2 || (str[pos + 1] != 0xA0 && str[pos + 1] != 0xFF)) MB_FAILURE(pos, 1); else if (avail < 3 || (str[pos + 2] != 0xA0 && str[pos + 2] != 0xFF)) MB_FAILURE(pos, 2); else MB_FAILURE(pos, 3); } else { /* JIS X 0212 hojo-kanji */ this_char = (c << 16) | (str[pos + 1] << 8) | str[pos + 2]; } pos += 3; } else if (c != 0xA0 && c != 0xFF) { /* character encoded in 1 code unit */ this_char = c; pos += 1; } else { MB_FAILURE(pos, 1); } } break; default: /* single-byte charsets */ this_char = str[pos++]; break; } *cursor = pos; return this_char; }
/* {{{ get_next_char */ inline static unsigned short get_next_char(enum entity_charset charset, unsigned char * str, int str_len, int * newpos, unsigned char * mbseq, int * mbseqlen, int *status) { int pos = *newpos; int mbpos = 0; int mbspace = *mbseqlen; unsigned short this_char = str[pos++]; unsigned char next_char; *status = SUCCESS; if (mbspace <= 0) { *mbseqlen = 0; return this_char; } MB_WRITE((unsigned char)this_char); switch (charset) { case cs_utf_8: { unsigned long utf = 0; int stat = 0; int more = 1; /* unpack utf-8 encoding into a wide char. * Code stolen from the mbstring extension */ do { if (this_char < 0x80) { more = 0; if(stat) { /* we didn't finish the UTF sequence correctly */ --pos; *status = FAILURE; } break; } else if (this_char < 0xc0) { switch (stat) { case 0x10: /* 2, 2nd */ case 0x21: /* 3, 3rd */ case 0x32: /* 4, 4th */ case 0x43: /* 5, 5th */ case 0x54: /* 6, 6th */ /* last byte in sequence */ more = 0; utf |= (this_char & 0x3f); this_char = (unsigned short)utf; break; case 0x20: /* 3, 2nd */ case 0x31: /* 4, 3rd */ case 0x42: /* 5, 4th */ case 0x53: /* 6, 5th */ /* penultimate char */ utf |= ((this_char & 0x3f) << 6); stat++; break; case 0x30: /* 4, 2nd */ case 0x41: /* 5, 3rd */ case 0x52: /* 6, 4th */ utf |= ((this_char & 0x3f) << 12); stat++; break; case 0x40: /* 5, 2nd */ case 0x51: utf |= ((this_char & 0x3f) << 18); stat++; break; case 0x50: /* 6, 2nd */ utf |= ((this_char & 0x3f) << 24); stat++; break; default: /* invalid */ *status = FAILURE; more = 0; } } /* lead byte */ else if (this_char < 0xe0) { stat = 0x10; /* 2 byte */ utf = (this_char & 0x1f) << 6; CHECK_LEN(pos, 1); } else if (this_char < 0xf0) { stat = 0x20; /* 3 byte */ utf = (this_char & 0xf) << 12; CHECK_LEN(pos, 2); } else if (this_char < 0xf8) { stat = 0x30; /* 4 byte */ utf = (this_char & 0x7) << 18; CHECK_LEN(pos, 3); } else if (this_char < 0xfc) { stat = 0x40; /* 5 byte */ utf = (this_char & 0x3) << 24; CHECK_LEN(pos, 4); } else if (this_char < 0xfe) { stat = 0x50; /* 6 byte */ utf = (this_char & 0x1) << 30; CHECK_LEN(pos, 5); } else { /* invalid; bail */ more = 0; *status = FAILURE; break; } if (more) { this_char = str[pos++]; MB_WRITE((unsigned char)this_char); } } while (more); } break; case cs_big5: case cs_gb2312: case cs_big5hkscs: { /* check if this is the first of a 2-byte sequence */ if (this_char >= 0xa1 && this_char <= 0xfe) { /* peek at the next char */ CHECK_LEN(pos, 1); next_char = str[pos]; if ((next_char >= 0x40 && next_char <= 0x7e) || (next_char >= 0xa1 && next_char <= 0xfe)) { /* yes, this a wide char */ this_char <<= 8; MB_WRITE(next_char); this_char |= next_char; pos++; } } break; } case cs_sjis: { /* check if this is the first of a 2-byte sequence */ if ( (this_char >= 0x81 && this_char <= 0x9f) || (this_char >= 0xe0 && this_char <= 0xef) ) { /* peek at the next char */ CHECK_LEN(pos, 1); next_char = str[pos]; if ((next_char >= 0x40 && next_char <= 0x7e) || (next_char >= 0x80 && next_char <= 0xfc)) { /* yes, this a wide char */ this_char <<= 8; MB_WRITE(next_char); this_char |= next_char; pos++; } } break; } case cs_eucjp: { /* check if this is the first of a multi-byte sequence */ if (this_char >= 0xa1 && this_char <= 0xfe) { /* peek at the next char */ CHECK_LEN(pos, 1); next_char = str[pos]; if (next_char >= 0xa1 && next_char <= 0xfe) { /* yes, this a jis kanji char */ this_char <<= 8; MB_WRITE(next_char); this_char |= next_char; pos++; } } else if (this_char == 0x8e) { /* peek at the next char */ CHECK_LEN(pos, 1); next_char = str[pos]; if (next_char >= 0xa1 && next_char <= 0xdf) { /* JIS X 0201 kana */ this_char <<= 8; MB_WRITE(next_char); this_char |= next_char; pos++; } } else if (this_char == 0x8f) { /* peek at the next two char */ unsigned char next2_char; CHECK_LEN(pos, 2); next_char = str[pos]; next2_char = str[pos+1]; if ((next_char >= 0xa1 && next_char <= 0xfe) && (next2_char >= 0xa1 && next2_char <= 0xfe)) { /* JIS X 0212 hojo-kanji */ this_char <<= 8; MB_WRITE(next_char); this_char |= next_char; pos++; this_char <<= 8; MB_WRITE(next2_char); this_char |= next2_char; pos++; } } break; } default: break; } MB_RETURN; }
SQLRETURN SQL_API SQLGetInfo( SQLHDBC hdbc, SQLUSMALLINT fInfoType, SQLPOINTER rgbInfoValue, SQLSMALLINT cbInfoValueMax, SQLSMALLINT FAR *pcbInfoValue) { if ( func_init("SQLGetInfo") != 0 ){ return SQL_ERROR; } switch( fInfoType ) { case SQL_ACCESSIBLE_PROCEDURES: if( rgbInfoValue && cbInfoValueMax > 1 ) { strcpy( (char*)rgbInfoValue, "N" ); // other driver } if( pcbInfoValue ) *pcbInfoValue = 1; return SQL_SUCCESS; case SQL_ACCESSIBLE_TABLES: if( rgbInfoValue && cbInfoValueMax > 1 ) { strcpy( (char*)rgbInfoValue, "N" ); // other driver } if( pcbInfoValue ) *pcbInfoValue = 1; return SQL_SUCCESS; case SQL_ACTIVE_CONNECTIONS: if( rgbInfoValue ) { *(SQLUSMALLINT *)rgbInfoValue = 10; // other driver if( pcbInfoValue ) *pcbInfoValue = sizeof( SQLUSMALLINT ); } return SQL_SUCCESS; case SQL_ACTIVE_STATEMENTS: if( rgbInfoValue ) { *(SQLUSMALLINT *)rgbInfoValue = 0; } if( pcbInfoValue ) *pcbInfoValue = sizeof( SQLUSMALLINT ); return SQL_SUCCESS; case SQL_ALTER_TABLE: if( rgbInfoValue ) { *(SQLUINTEGER *)rgbInfoValue = SQL_AT_ADD_COLUMN | SQL_AT_DROP_COLUMN; } if( pcbInfoValue ) *pcbInfoValue = sizeof( SQLUINTEGER ); return SQL_SUCCESS; case SQL_BOOKMARK_PERSISTENCE: if( rgbInfoValue ) { *(SQLUINTEGER *)rgbInfoValue = 0; // other driver CHECK_LEN(SQLUINTEGER); } RESULT_LEN(SQLUINTEGER); return SQL_SUCCESS; case SQL_CATALOG_LOCATION: if( rgbInfoValue ) { *(SQLUSMALLINT *)rgbInfoValue = 0; // other driver } if( pcbInfoValue ) *pcbInfoValue = sizeof( SQLUSMALLINT ); return SQL_SUCCESS; case SQL_CATALOG_NAME_SEPARATOR: if( rgbInfoValue && cbInfoValueMax > 1 ) { strcpy( (char*)rgbInfoValue, "" ); // other driver } if( pcbInfoValue ) *pcbInfoValue = 0; return SQL_SUCCESS; case SQL_CATALOG_TERM: if( rgbInfoValue && cbInfoValueMax > 7 ) { strcpy( (char*)rgbInfoValue, "catalog" ); } if( pcbInfoValue ) *pcbInfoValue = 7; return SQL_SUCCESS; case SQL_CATALOG_USAGE: if( rgbInfoValue ) { *(SQLUINTEGER *)rgbInfoValue = 0; } if( pcbInfoValue ) *pcbInfoValue = sizeof( SQLUINTEGER ); return SQL_SUCCESS; case SQL_COLUMN_ALIAS: if( rgbInfoValue && cbInfoValueMax > 1 ) { strcpy( (char*)rgbInfoValue, "N" ); // other driver } if( pcbInfoValue ) *pcbInfoValue = 1; return SQL_SUCCESS; case SQL_CONCAT_NULL_BEHAVIOR: if( rgbInfoValue && cbInfoValueMax > 1 ) { *(short *)rgbInfoValue = SQL_CB_NULL; // other driver } if( pcbInfoValue ) *pcbInfoValue = sizeof(short); return SQL_SUCCESS; case SQL_CONVERT_BIGINT: if( rgbInfoValue ) { *(SQLUINTEGER *)rgbInfoValue = 0; CHECK_LEN(SQLUINTEGER); } RESULT_LEN(SQLUINTEGER); return SQL_SUCCESS; case SQL_CONVERT_BINARY: if( rgbInfoValue ) { *(SQLUINTEGER *)rgbInfoValue = 0; CHECK_LEN(SQLUINTEGER); } RESULT_LEN(SQLUINTEGER); return SQL_SUCCESS; case SQL_CONVERT_BIT: if( rgbInfoValue ) { *(SQLUINTEGER *)rgbInfoValue = 0; CHECK_LEN(SQLUINTEGER); } RESULT_LEN(SQLUINTEGER); return SQL_SUCCESS; case SQL_CONVERT_CHAR: if( rgbInfoValue ) { *(SQLUINTEGER *)rgbInfoValue = 0x00008002; // other driver CHECK_LEN(SQLUINTEGER); } RESULT_LEN(SQLUINTEGER); return SQL_SUCCESS; case SQL_CONVERT_DATE: if( rgbInfoValue ) { *(SQLUINTEGER *)rgbInfoValue = 0x00008101; // other driver CHECK_LEN(SQLUINTEGER); } RESULT_LEN(SQLUINTEGER); return SQL_SUCCESS; case SQL_CONVERT_DECIMAL: if( rgbInfoValue ) { *(SQLUINTEGER *)rgbInfoValue = 0; CHECK_LEN(SQLUINTEGER); } RESULT_LEN(SQLUINTEGER); return SQL_SUCCESS; case SQL_CONVERT_DOUBLE: if( rgbInfoValue ) { *(SQLUINTEGER *)rgbInfoValue = 0; CHECK_LEN(SQLUINTEGER); } RESULT_LEN(SQLUINTEGER); return SQL_SUCCESS; case SQL_CONVERT_FLOAT: if( rgbInfoValue ) { *(SQLUINTEGER *)rgbInfoValue = 0; CHECK_LEN(SQLUINTEGER); } RESULT_LEN(SQLUINTEGER); return SQL_SUCCESS; case SQL_CONVERT_FUNCTIONS: if( rgbInfoValue ) { *(SQLUINTEGER *)rgbInfoValue = 0; // 何もなし CHECK_LEN(SQLUINTEGER); } RESULT_LEN(SQLUINTEGER); return SQL_SUCCESS; case SQL_CONVERT_INTEGER: if( rgbInfoValue ) { *(SQLUINTEGER *)rgbInfoValue = 0; CHECK_LEN(SQLUINTEGER); } RESULT_LEN(SQLUINTEGER); return SQL_SUCCESS; case SQL_CONVERT_LONGVARBINARY: if( rgbInfoValue ) { *(SQLUINTEGER *)rgbInfoValue = 0; CHECK_LEN(SQLUINTEGER); } RESULT_LEN(SQLUINTEGER); return SQL_SUCCESS; case SQL_CONVERT_LONGVARCHAR: if( rgbInfoValue ) { *(SQLUINTEGER *)rgbInfoValue = 0; CHECK_LEN(SQLUINTEGER); } RESULT_LEN(SQLUINTEGER); return SQL_SUCCESS; case SQL_CONVERT_NUMERIC: if( rgbInfoValue ) { *(SQLUINTEGER *)rgbInfoValue = 0x00008101; // other driver CHECK_LEN(SQLUINTEGER); } RESULT_LEN(SQLUINTEGER); return SQL_SUCCESS; case SQL_CURSOR_COMMIT_BEHAVIOR: if( rgbInfoValue ) { *(SQLUSMALLINT *)rgbInfoValue = SQL_CB_PRESERVE; CHECK_LEN(SQLUSMALLINT); } RESULT_LEN(SQLUSMALLINT); return SQL_SUCCESS; case SQL_CURSOR_ROLLBACK_BEHAVIOR: if( rgbInfoValue ) { *(SQLUSMALLINT *)rgbInfoValue = SQL_CB_DELETE; CHECK_LEN(SQLUSMALLINT); } RESULT_LEN(SQLUSMALLINT); return SQL_SUCCESS; case SQL_DATABASE_NAME: if( rgbInfoValue && cbInfoValueMax > 10 ) { strcpy( (char*)rgbInfoValue, "hiveodbc" ); } if( pcbInfoValue ) *pcbInfoValue = 10; return SQL_SUCCESS; case SQL_DBMS_NAME: if( rgbInfoValue && cbInfoValueMax > 10 ) { strcpy( (char*)rgbInfoValue, "hiveodbc" ); } if( pcbInfoValue ) *pcbInfoValue = 8; return SQL_SUCCESS; case SQL_DBMS_VER: if( rgbInfoValue && cbInfoValueMax > 10 ) { strcpy( (char*)rgbInfoValue, "01.01.0000" ); } if( pcbInfoValue ) *pcbInfoValue = 10; return SQL_SUCCESS; case SQL_DATA_SOURCE_READ_ONLY: if( rgbInfoValue ) { strcpy( (char*)rgbInfoValue, "N" ); } if( pcbInfoValue ) *pcbInfoValue = 1; return SQL_SUCCESS; case SQL_DEFAULT_TXN_ISOLATION: if( rgbInfoValue ) { *(SQLUINTEGER *)rgbInfoValue = SQL_TXN_READ_COMMITTED; CHECK_LEN(SQLUINTEGER); } RESULT_LEN(SQLUINTEGER); return SQL_SUCCESS; case SQL_DRIVER_ODBC_VER: if( rgbInfoValue && cbInfoValueMax > 5 ) { strcpy( (char*)rgbInfoValue, "01.00" ); } if( pcbInfoValue ) *pcbInfoValue = 5; return SQL_SUCCESS; case SQL_DRIVER_NAME: if( rgbInfoValue && cbInfoValueMax > 10 ) { strcpy( (char*)rgbInfoValue, "hiveodbc.dll" ); } if( pcbInfoValue ) *pcbInfoValue = 12; return SQL_SUCCESS; case SQL_DRIVER_VER: if( rgbInfoValue && cbInfoValueMax > 10 ) { strcpy( (char*)rgbInfoValue, "01.00.0000" ); } if( pcbInfoValue ) *pcbInfoValue = 10; return SQL_SUCCESS; case SQL_DYNAMIC_CURSOR_ATTRIBUTES1: if( rgbInfoValue ) { *(SQLUINTEGER *)rgbInfoValue = SQL_CA1_NEXT; CHECK_LEN(SQLUINTEGER); } RESULT_LEN(SQLUINTEGER); return SQL_SUCCESS; case SQL_EXPRESSIONS_IN_ORDERBY: if( rgbInfoValue && cbInfoValueMax > 1 ) { strcpy( (char*)rgbInfoValue, "N" ); } if( pcbInfoValue ) *pcbInfoValue = 1; return SQL_SUCCESS; case SQL_FETCH_DIRECTION: if( rgbInfoValue ) { *(SQLUINTEGER *)rgbInfoValue = SQL_FD_FETCH_NEXT; CHECK_LEN(SQLUINTEGER); } RESULT_LEN(SQLUINTEGER); return SQL_SUCCESS; case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1: if( rgbInfoValue ) { *(SQLUINTEGER *)rgbInfoValue = SQL_CA1_NEXT; CHECK_LEN(SQLUINTEGER); } RESULT_LEN(SQLUINTEGER); return SQL_SUCCESS; case SQL_GETDATA_EXTENSIONS: if( rgbInfoValue ) { *(long *)rgbInfoValue = SQL_GD_ANY_COLUMN | SQL_GD_ANY_ORDER | SQL_GD_BOUND | SQL_GD_BLOCK; } if( pcbInfoValue ) *pcbInfoValue = 4; return SQL_SUCCESS; case SQL_GROUP_BY: if( rgbInfoValue ) { *(short *)rgbInfoValue = SQL_GB_GROUP_BY_EQUALS_SELECT; CHECK_LEN(SQLUSMALLINT); } RESULT_LEN(SQLUSMALLINT); return SQL_SUCCESS; case SQL_IDENTIFIER_QUOTE_CHAR: if( rgbInfoValue ) { strcpy( (char*)rgbInfoValue, "" ); } if( pcbInfoValue ) *pcbInfoValue = 1; return SQL_SUCCESS; case SQL_IDENTIFIER_CASE: if( rgbInfoValue ) { *(short *)rgbInfoValue = SQL_IC_UPPER; CHECK_LEN(SQLUSMALLINT); } RESULT_LEN(SQLUSMALLINT); return SQL_SUCCESS; case SQL_KEYSET_CURSOR_ATTRIBUTES1: if( rgbInfoValue ) { *(SQLUINTEGER *)rgbInfoValue = SQL_CA1_NEXT; CHECK_LEN(SQLUINTEGER); } RESULT_LEN(SQLUINTEGER); return SQL_SUCCESS; case SQL_LIKE_ESCAPE_CLAUSE: if( rgbInfoValue ) { strcpy( (char*)rgbInfoValue, "N" ); } if( pcbInfoValue ) *pcbInfoValue = 1; return SQL_SUCCESS; case SQL_LOCK_TYPES: if( rgbInfoValue ) { *(long *)rgbInfoValue = SQL_LCK_NO_CHANGE; } if( pcbInfoValue ) *pcbInfoValue = 4; return SQL_SUCCESS; case SQL_MAX_CATALOG_NAME_LEN: if( rgbInfoValue ) { *(SQLUSMALLINT *)rgbInfoValue = 0; // other driver CHECK_LEN(SQLUSMALLINT); } RESULT_LEN(SQLUSMALLINT); return SQL_SUCCESS; case SQL_MAX_COLUMN_NAME_LEN: if( rgbInfoValue ) { *(short *)rgbInfoValue = 31; } if( pcbInfoValue ) *pcbInfoValue = 2; return SQL_SUCCESS; case SQL_MAX_CURSOR_NAME_LEN: if( rgbInfoValue ) { *(short *)rgbInfoValue = 31; // other driver (max 18) } if( pcbInfoValue ) *pcbInfoValue = 2; return SQL_SUCCESS; case SQL_MAX_PROCEDURE_NAME_LEN: if( rgbInfoValue ) { *(SQLUSMALLINT *)rgbInfoValue = 27; // other driver 31? CHECK_LEN(SQLUSMALLINT); } RESULT_LEN(SQLUSMALLINT); return SQL_SUCCESS; case SQL_MAX_SCHEMA_NAME_LEN: if( rgbInfoValue ) { *(SQLUSMALLINT *)rgbInfoValue = 0; // other driver CHECK_LEN(SQLUSMALLINT); } RESULT_LEN(SQLUSMALLINT); return SQL_SUCCESS; case SQL_MAX_TABLE_NAME_LEN: if( rgbInfoValue ) { *(short *)rgbInfoValue = 31; } if( pcbInfoValue ) *pcbInfoValue = 2; return SQL_SUCCESS; case SQL_MULT_RESULT_SETS: if( rgbInfoValue ) { strcpy( (char*)rgbInfoValue, "N" ); } if( pcbInfoValue ) *pcbInfoValue = 1; return SQL_SUCCESS; case SQL_MULTIPLE_ACTIVE_TXN: if( rgbInfoValue ) { strcpy( (char*)rgbInfoValue, "Y" ); } if( pcbInfoValue ) *pcbInfoValue = 1; return SQL_SUCCESS; case SQL_NULL_COLLATION: if( rgbInfoValue ) { *(short *)rgbInfoValue = 0; // ? } if( pcbInfoValue ) *pcbInfoValue = 2; return SQL_SUCCESS; case SQL_NEED_LONG_DATA_LEN: if( rgbInfoValue ) { *(char *)rgbInfoValue = 'N'; } if( pcbInfoValue ) *pcbInfoValue = 1; return SQL_SUCCESS; case SQL_NUMERIC_FUNCTIONS: if( rgbInfoValue ) { *(long *)rgbInfoValue = 0; // 何もなし } if( pcbInfoValue ) *pcbInfoValue = 4; return SQL_SUCCESS; case SQL_ODBC_API_CONFORMANCE: if( rgbInfoValue ) { *(short *)rgbInfoValue = SQL_OAC_LEVEL1; } if( pcbInfoValue ) *pcbInfoValue = sizeof( SQLUSMALLINT ); return SQL_SUCCESS; case SQL_ORDER_BY_COLUMNS_IN_SELECT: if( rgbInfoValue && cbInfoValueMax > 1 ) { strcpy( (char*)rgbInfoValue, "N" ); } if( pcbInfoValue ) *pcbInfoValue = 1; return SQL_SUCCESS; case SQL_OUTER_JOINS: if( rgbInfoValue && cbInfoValueMax > 1 ) { strcpy( (char*)rgbInfoValue, "Y" ); } if( pcbInfoValue ) *pcbInfoValue = 1; return SQL_SUCCESS; case SQL_OWNER_TERM: if( rgbInfoValue && cbInfoValueMax > 5 ) { strcpy( (char*)rgbInfoValue, "OWNER" ); } if( pcbInfoValue ) *pcbInfoValue = 5; return SQL_SUCCESS; case SQL_POSITIONED_STATEMENTS: if( rgbInfoValue ) { *(SQLUINTEGER *)rgbInfoValue = 0; CHECK_LEN(SQLUINTEGER); } RESULT_LEN(SQLUINTEGER); return SQL_SUCCESS; case SQL_POS_OPERATIONS: if( rgbInfoValue ) { *(SQLUINTEGER *)rgbInfoValue = 0; CHECK_LEN(SQLUINTEGER); } RESULT_LEN(SQLUINTEGER); return SQL_SUCCESS; case SQL_PROCEDURES: if( rgbInfoValue ) { strcpy( (char*)rgbInfoValue, "Y" ); } if( pcbInfoValue ) *pcbInfoValue = 1; return SQL_SUCCESS; case SQL_QUOTED_IDENTIFIER_CASE: if( rgbInfoValue ) { *(short *)rgbInfoValue = SQL_IC_UPPER; } if( pcbInfoValue ) *pcbInfoValue = 2; return SQL_SUCCESS; case SQL_ROW_UPDATES: if( rgbInfoValue ) { strcpy( (char*)rgbInfoValue, "Y" ); } if( pcbInfoValue ) *pcbInfoValue = 1; return SQL_SUCCESS; case SQL_SCROLL_CONCURRENCY: if( rgbInfoValue ) { *(long *)rgbInfoValue = SQL_SCCO_READ_ONLY; } if( pcbInfoValue ) *pcbInfoValue = 4; return SQL_SUCCESS; case SQL_SCROLL_OPTIONS: if( rgbInfoValue ) { *(long *)rgbInfoValue = SQL_SO_FORWARD_ONLY; } if( pcbInfoValue ) *pcbInfoValue = 4; return SQL_SUCCESS; case SQL_SEARCH_PATTERN_ESCAPE: if( rgbInfoValue && cbInfoValueMax > 1 ) { strcpy( (char*)rgbInfoValue, "" ); } if( pcbInfoValue ) *pcbInfoValue = 0; return SQL_SUCCESS; case SQL_STATIC_CURSOR_ATTRIBUTES1: // ODBC 3.0 if( rgbInfoValue ) { *(SQLUINTEGER *)rgbInfoValue = SQL_CA1_NEXT; CHECK_LEN(SQLUINTEGER); } RESULT_LEN(SQLUINTEGER); return SQL_SUCCESS; case SQL_STATIC_SENSITIVITY: if( rgbInfoValue ) { *(long *)rgbInfoValue = 0; // 何も出来ない } if( pcbInfoValue ) *pcbInfoValue = 4; return SQL_SUCCESS; case SQL_STRING_FUNCTIONS: if( rgbInfoValue ) { *(long *)rgbInfoValue = 0; // 何もなし } if( pcbInfoValue ) *pcbInfoValue = 4; return SQL_SUCCESS; case SQL_SYSTEM_FUNCTIONS: if( rgbInfoValue ) { *(long *)rgbInfoValue = 0; // 何もなし } if( pcbInfoValue ) *pcbInfoValue = 4; return SQL_SUCCESS; case SQL_TIMEDATE_FUNCTIONS: if( rgbInfoValue ) { *(long *)rgbInfoValue = 0; // 何もなし } if( pcbInfoValue ) *pcbInfoValue = 4; return SQL_SUCCESS; case SQL_TXN_CAPABLE: if( rgbInfoValue ) { *(short *)rgbInfoValue = SQL_TC_DDL_COMMIT; } if( pcbInfoValue ) *pcbInfoValue = 2; return SQL_SUCCESS; case SQL_TXN_ISOLATION_OPTION: if( rgbInfoValue ) { *(long *)rgbInfoValue = SQL_TXN_READ_COMMITTED | SQL_TXN_REPEATABLE_READ | SQL_TXN_SERIALIZABLE ; } if( pcbInfoValue ) *pcbInfoValue = 4; return SQL_SUCCESS; case SQL_UNION: if( rgbInfoValue ) { *(SQLUINTEGER *)rgbInfoValue = SQL_U_UNION | SQL_U_UNION_ALL; CHECK_LEN(SQLUINTEGER); } RESULT_LEN(SQLUINTEGER); return SQL_SUCCESS; } if( pcbInfoValue ) *pcbInfoValue = 0; debuglog("unknown SQLGetInfo(%d)", fInfoType ); return SQL_ERROR; }
static void command_run(struct watch *w, uint8_t events) { union { char buf[256]; enum command cmd; struct command_color cmd_color; struct command_color_mask cmd_color_mask; struct command_sequence cmd_seq; } cmdbuf; ssize_t z = recv(Command_sock, cmdbuf.buf, sizeof(cmdbuf), 0); if (z < 0) { fprintf(stderr, "command recv: %m\n"); return; } #define CHECK_LEN(T) \ if (z < sizeof(cmdbuf.T)) \ { \ fprintf(stderr, "command len: %zd for %s\n", z, #T); \ return; \ } CHECK_LEN(cmd); enum color c; color_t ct = {}; enum led led; if (z >= sizeof(cmdbuf.cmd_color)) { color_cpy(ct, cmdbuf.cmd_color.color); if ((led = cmdbuf.cmd_color.led) >= LED_COUNT) return; } switch (cmdbuf.cmd) { case COMMAND_NULL: break; case COMMAND_COLOR_SET: if (z >= sizeof(cmdbuf.cmd_color_mask)) for_color (c) ct[c] = (ct[c] & cmdbuf.cmd_color_mask.mask[c]) | (Command_color[led][c] & ~cmdbuf.cmd_color_mask.mask[c]); command_color_set(ct, led); break; case COMMAND_COLOR_ADD: CHECK_LEN(cmd_color); for_color (c) ct[c] = Command_color[led][c] + ct[c]; command_color_set(ct, led); break; case COMMAND_COLOR_SUB: CHECK_LEN(cmd_color); for_color (c) ct[c] = Command_color[led][c] - ct[c]; command_color_set(ct, led); break; case COMMAND_SEQUENCE: command_sequence(cmdbuf.cmd_seq.seq, (z - offsetof(struct command_sequence, seq))/sizeof(*cmdbuf.cmd_seq.seq), led); break; } #undef CHECK_LEN }
static inline void sniff_loop_tcp(session_t *s, int len, const u_char *packet, const struct iphdr *ip, int size_ip) { /* XXX here, make some struct with known TCP services, and demangler-function */ const struct tcphdr *tcp; int size_tcp; connection_t *hdr; const char *payload; int size_payload; CHECK_LEN(sizeof(struct tcphdr)) tcp = (struct tcphdr*) (packet); size_tcp = TH_OFF(tcp)*4; if (size_tcp < 20) { debug_error("sniff_loop_tcp() * Invalid TCP header length: %u bytes\n", size_tcp); return; } size_payload = g_ntohs(ip->ip_len) - (size_ip + size_tcp); CHECK_LEN(size_tcp + size_payload); payload = (char *) (packet + size_tcp); hdr = sniff_tcp_find_connection(ip, tcp); debug_function("sniff_loop_tcp() IP/TCP %15s:%5d <==> %15s:%5d %s (SEQ: %lx ACK: %lx len: %d)\n", _inet_ntoa(hdr->srcip), /* src ip */ hdr->srcport, /* src port */ _inet_ntoa(hdr->dstip), /* dest ip */ hdr->dstport, /* dest port */ tcp_print_flags(tcp->th_flags), /* tcp flags */ g_htonl(tcp->th_seq), /* seq */ g_htonl(tcp->th_ack), /* ack */ size_payload); /* payload len */ /* XXX check tcp flags */ if (!size_payload) return; /* XXX what proto ? check based on ip + port? */ if (hdr->dstport == 80 || hdr->srcport == 80) { /* HTTP [basic check on magic values, ~80% hit] */ static const char http_magic11[] = { 'H', 'T', 'T', 'P', '/', '1', '.', '1', ' ' }; /* HTTP/1.1 */ static const char http_magic10[] = { 'H', 'T', 'T', 'P', '/', '1', '.', '0', ' ' }; /* HTTP/1.0 */ static const char http_get_magic[] = { 'G', 'E', 'T', ' ' }; /* GET */ static const char http_post_magic[] = { 'P', 'O', 'S', 'T', ' ' }; /* POST */ /* SERVER REPLIES: */ if ( (size_payload > sizeof(http_magic10) && !memcmp(payload, http_magic10, sizeof(http_magic10))) || (size_payload > sizeof(http_magic11) && !memcmp(payload, http_magic11, sizeof(http_magic11))) ) { // debug_error("HTTP DATA FOLLOW\n"); // tcp_print_payload((u_char *) payload, size_payload); return; /* done */ } /* CLIENT REQUESTs: */ if ( (size_payload > sizeof(http_get_magic) && !memcmp(payload, http_get_magic, sizeof(http_get_magic))) || (size_payload > sizeof(http_post_magic) && !memcmp(payload, http_post_magic, sizeof(http_post_magic))) ) { // debug_error("HTTP DATA FOLLOW?\n"); // tcp_print_payload((u_char *) payload, size_payload); return; /* done */ } } sniff_gg(s, hdr, (gg_header *) payload, size_payload); /* GG [no check, ~3% hit] */ }