static void log_packet_common(struct sbuff *m, u_int8_t pf, unsigned int hooknum, const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const struct nf_loginfo *loginfo, const char *prefix) { sb_add(m, KERN_SOH "%c%sIN=%s OUT=%s ", '0' + loginfo->u.log.level, prefix, in ? in->name : "", out ? out->name : ""); #ifdef CONFIG_BRIDGE_NETFILTER if (skb->nf_bridge) { const struct net_device *physindev; const struct net_device *physoutdev; physindev = skb->nf_bridge->physindev; if (physindev && in != physindev) sb_add(m, "PHYSIN=%s ", physindev->name); physoutdev = skb->nf_bridge->physoutdev; if (physoutdev && out != physoutdev) sb_add(m, "PHYSOUT=%s ", physoutdev->name); } #endif }
static inline int db_int2ldap_bool(struct sbuf* buf, db_fld_t* fld) { if (fld->v.int4) return sb_add(buf, "TRUE", 4); else return sb_add(buf, "FALSE", 5); }
static int dump_udp_header(struct sbuff *m, const struct sk_buff *skb, u8 proto, int fragment, unsigned int offset) { struct udphdr _udph; const struct udphdr *uh; if (proto == IPPROTO_UDP) /* Max length: 10 "PROTO=UDP " */ sb_add(m, "PROTO=UDP "); else /* Max length: 14 "PROTO=UDPLITE " */ sb_add(m, "PROTO=UDPLITE "); if (fragment) goto out; /* Max length: 25 "INCOMPLETE [65535 bytes] " */ uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph); if (uh == NULL) { sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - offset); return 1; } /* Max length: 20 "SPT=65535 DPT=65535 " */ sb_add(m, "SPT=%u DPT=%u LEN=%u ", ntohs(uh->source), ntohs(uh->dest), ntohs(uh->len)); out: return 0; }
static inline int db_bit2ldap_bitstr(struct sbuf* buf, db_fld_t* fld) { int rv, i; rv = 0; rv |= sb_add(buf, "'", 1); i = 1 << (sizeof(fld->v.int4) * 8 - 1); while(i) { rv |= sb_add(buf, (fld->v.int4 & i)?"1":"0", 1); i = i >> 1; } rv |= sb_add(buf, "'B", 2); return rv; }
static void ip6t_log_packet(unsigned int pf, unsigned int hooknum, const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const struct nf_loginfo *loginfo, const char *prefix) { struct sbuff *m = sb_open(); if (!loginfo) loginfo = &default_loginfo; sb_add(m, "<%d>%sIN=%s OUT=%s ", loginfo->u.log.level, prefix, in ? in->name : "", out ? out->name : ""); /* MAC logging for input path only. */ if (in && !out) dump_mac_header(m, loginfo, skb); dump_packet(m, loginfo, skb, skb_network_offset(skb), 1); sb_close(m); }
static inline int db_uint2ldap_int(struct sbuf* buf, db_fld_t* fld) { char* num; int len, v; v = fld->v.int4; num = int2str(v, &len); return sb_add(buf, num, len); }
static void AppendStr(char** buf, const char* s) { size_t len = strlen(s); char* start = sb_add(*buf, len); for(int i = 0; i < len; ++i) { start[i] = s[i]; } }
static inline int db_datetime2ldap_gentime(struct sbuf* buf, db_fld_t* fld) { char tmp[16]; struct tm* t; t = gmtime(&fld->v.time); if (strftime(tmp, sizeof(tmp), "%Y%m%d%H%M%SZ", t) != sizeof(tmp)-1) { ERR("ldap: Error while converting time_t value to LDAP format\n"); return -1; } return sb_add(buf, tmp, sizeof(tmp)-1); }
static inline int db_int2ldap_str(struct sbuf* buf, db_fld_t* fld) { int len; char tmp[INT2STR_MAX_LEN + 1]; len = snprintf(tmp, INT2STR_MAX_LEN + 1, "%-d", fld->v.int4); if (len < 0 || len >= INT2STR_MAX_LEN + 1) { BUG("ldap: Error while converting integer to string\n"); return -1; } return sb_add(buf, tmp, len); }
static inline int db_float2ldap_str(struct sbuf* buf, db_fld_t* fld) { char tmp[16]; int len; len = snprintf(tmp, 16, "%-10.2f", fld->v.flt); if (len < 0 || len >= 16) { BUG("ldap: Error while converting float to string\n"); return -1; } return sb_add(buf, tmp, len); }
static void dump_ipv6_mac_header(struct sbuff *m, const struct nf_loginfo *info, const struct sk_buff *skb) { struct net_device *dev = skb->dev; unsigned int logflags = 0; if (info->type == NF_LOG_TYPE_LOG) logflags = info->u.log.logflags; if (!(logflags & XT_LOG_MACDECODE)) goto fallback; switch (dev->type) { case ARPHRD_ETHER: sb_add(m, "MACSRC=%pM MACDST=%pM MACPROTO=%04x ", eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest, ntohs(eth_hdr(skb)->h_proto)); return; default: break; } fallback: sb_add(m, "MAC="); if (dev->hard_header_len && skb->mac_header != skb->network_header) { const unsigned char *p = skb_mac_header(skb); unsigned int len = dev->hard_header_len; unsigned int i; if (dev->type == ARPHRD_SIT) { p -= ETH_HLEN; if (p < skb->head) p = NULL; } if (p != NULL) { sb_add(m, "%02x", *p++); for (i = 1; i < len; i++) sb_add(m, ":%02x", *p++); } sb_add(m, " "); if (dev->type == ARPHRD_SIT) { const struct iphdr *iph = (struct iphdr *)skb_mac_header(skb); sb_add(m, "TUNNEL=%pI4->%pI4 ", &iph->saddr, &iph->daddr); } } else sb_add(m, " "); }
int main(int argc, char **argv) { int i; UpClient *upclient; IxpClient *client; signals_setup(&quit_handler); client = ixp_nsmount("wmii"); if(client == NULL) { printf("ixp_nsmount: %s\n", ixp_errbuf()); abort(); } mainloop = g_main_loop_new(NULL, FALSE); upclient = up_client_new(); sb_init(&sb, client); sb_add(&sb, &sbe_ac); for(i = 0; i < MAX_BATTERIES; i++) { sb_add(&sb, &sbe_batteries[i]); } up_client_enumerate_devices_sync(upclient, NULL, NULL); g_signal_connect(upclient, "device-added", G_CALLBACK(device_added_cb), NULL); g_signal_connect(upclient, "device-removed", G_CALLBACK(device_removed_cb), NULL); g_signal_connect(upclient, "device-changed", G_CALLBACK(device_changed_cb), NULL); g_signal_connect(upclient, "changed", G_CALLBACK(changed_cb), NULL); update_sb(upclient); g_main_loop_run(mainloop); sb_finish(&sb); ixp_unmount(client); }
static void ipt_log_packet(u_int8_t pf, unsigned int hooknum, const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const struct nf_loginfo *loginfo, const char *prefix) { struct sbuff *m = sb_open(); if (!loginfo) loginfo = &default_loginfo; sb_add(m, "<%d>%sIN=%s OUT=%s ", loginfo->u.log.level, prefix, in ? in->name : "", out ? out->name : ""); #ifdef CONFIG_BRIDGE_NETFILTER if (skb->nf_bridge) { const struct net_device *physindev; const struct net_device *physoutdev; physindev = skb->nf_bridge->physindev; if (physindev && in != physindev) sb_add(m, "PHYSIN=%s ", physindev->name); physoutdev = skb->nf_bridge->physoutdev; if (physoutdev && out != physoutdev) sb_add(m, "PHYSOUT=%s ", physoutdev->name); } #endif if (in != NULL) dump_mac_header(m, loginfo, skb); dump_packet(m, loginfo, skb, 0); sb_close(m); }
static void dump_sk_uid_gid(struct sbuff *m, struct sock *sk) { if (!sk || sk->sk_state == TCP_TIME_WAIT) return; read_lock_bh(&sk->sk_callback_lock); if (sk->sk_socket && sk->sk_socket->file) { const struct cred *cred = sk->sk_socket->file->f_cred; sb_add(m, "UID=%u GID=%u ", from_kuid_munged(&init_user_ns, cred->fsuid), from_kgid_munged(&init_user_ns, cred->fsgid)); } read_unlock_bh(&sk->sk_callback_lock); }
static void dump_ipv4_mac_header(struct sbuff *m, const struct nf_loginfo *info, const struct sk_buff *skb) { struct net_device *dev = skb->dev; unsigned int logflags = 0; if (info->type == NF_LOG_TYPE_LOG) logflags = info->u.log.logflags; if (!(logflags & XT_LOG_MACDECODE)) goto fallback; switch (dev->type) { case ARPHRD_ETHER: sb_add(m, "MACSRC=%pM MACDST=%pM MACPROTO=%04x ", eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest, ntohs(eth_hdr(skb)->h_proto)); return; default: break; } fallback: sb_add(m, "MAC="); if (dev->hard_header_len && skb->mac_header != skb->network_header) { const unsigned char *p = skb_mac_header(skb); unsigned int i; sb_add(m, "%02x", *p++); for (i = 1; i < dev->hard_header_len; i++, p++) sb_add(m, ":%02x", *p); } sb_add(m, " "); }
static void ipt_log_packet(u_int8_t pf, unsigned int hooknum, const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const struct nf_loginfo *loginfo, const char *prefix) { struct sbuff *m = sb_open(); if (!loginfo) loginfo = &default_loginfo; sb_add(m, "<%d>%sIN=%s OUT=%s ", loginfo->u.log.level, prefix, in ? in->name : "", out ? out->name : ""); #ifdef CONFIG_BRIDGE_NETFILTER if (skb->nf_bridge) { const struct net_device *physindev; const struct net_device *physoutdev; physindev = skb->nf_bridge->physindev; if (physindev && in != physindev) sb_add(m, "PHYSIN=%s ", physindev->name); physoutdev = skb->nf_bridge->physoutdev; if (physoutdev && out != physoutdev) sb_add(m, "PHYSOUT=%s ", physoutdev->name); } #endif if (in && !out) { /* MAC logging for input chain only. */ sb_add(m, "MAC="); if (skb->dev && skb->dev->hard_header_len && skb->mac_header != skb->network_header) { int i; const unsigned char *p = skb_mac_header(skb); for (i = 0; i < skb->dev->hard_header_len; i++,p++) sb_add(m, "%02x%c", *p, i==skb->dev->hard_header_len - 1 ? ' ':':'); } else sb_add(m, " "); } dump_packet(m, loginfo, skb, 0); sb_close(m); }
int main(int arg, char **argv) { int i; int *arr = NULL; for (i=0; i < 1000000; ++i) sb_push(arr, i); assert(sb_count(arr) == 1000000); for (i=0; i < 1000000; ++i) assert(arr[i] == i); sb_free(arr); arr = NULL; for (i=0; i < 1000; ++i) sb_add(arr, 1000); assert(sb_count(arr) == 1000000); return 0; }
/* One level of recursion won't kill us */ static void dump_ipv4_packet(struct sbuff *m, const struct nf_loginfo *info, const struct sk_buff *skb, unsigned int iphoff) { struct iphdr _iph; const struct iphdr *ih; unsigned int logflags; if (info->type == NF_LOG_TYPE_LOG) logflags = info->u.log.logflags; else logflags = NF_LOG_MASK; ih = skb_header_pointer(skb, iphoff, sizeof(_iph), &_iph); if (ih == NULL) { sb_add(m, "TRUNCATED"); return; } /* Important fields: * TOS, len, DF/MF, fragment offset, TTL, src, dst, options. */ /* Max length: 40 "SRC=255.255.255.255 DST=255.255.255.255 " */ sb_add(m, "SRC=%pI4 DST=%pI4 ", &ih->saddr, &ih->daddr); /* Max length: 46 "LEN=65535 TOS=0xFF PREC=0xFF TTL=255 ID=65535 " */ sb_add(m, "LEN=%u TOS=0x%02X PREC=0x%02X TTL=%u ID=%u ", ntohs(ih->tot_len), ih->tos & IPTOS_TOS_MASK, ih->tos & IPTOS_PREC_MASK, ih->ttl, ntohs(ih->id)); /* Max length: 6 "CE DF MF " */ if (ntohs(ih->frag_off) & IP_CE) sb_add(m, "CE "); if (ntohs(ih->frag_off) & IP_DF) sb_add(m, "DF "); if (ntohs(ih->frag_off) & IP_MF) sb_add(m, "MF "); /* Max length: 11 "FRAG:65535 " */ if (ntohs(ih->frag_off) & IP_OFFSET) sb_add(m, "FRAG:%u ", ntohs(ih->frag_off) & IP_OFFSET); if ((logflags & XT_LOG_IPOPT) && ih->ihl * 4 > sizeof(struct iphdr)) { const unsigned char *op; unsigned char _opt[4 * 15 - sizeof(struct iphdr)]; unsigned int i, optsize; optsize = ih->ihl * 4 - sizeof(struct iphdr); op = skb_header_pointer(skb, iphoff+sizeof(_iph), optsize, _opt); if (op == NULL) { sb_add(m, "TRUNCATED"); return; } /* Max length: 127 "OPT (" 15*4*2chars ") " */ sb_add(m, "OPT ("); for (i = 0; i < optsize; i++) sb_add(m, "%02X", op[i]); sb_add(m, ") "); } switch (ih->protocol) { case IPPROTO_TCP: if (dump_tcp_header(m, skb, ih->protocol, ntohs(ih->frag_off) & IP_OFFSET, iphoff+ih->ihl*4, logflags)) return; break; case IPPROTO_UDP: case IPPROTO_UDPLITE: if (dump_udp_header(m, skb, ih->protocol, ntohs(ih->frag_off) & IP_OFFSET, iphoff+ih->ihl*4)) return; break; case IPPROTO_ICMP: { struct icmphdr _icmph; const struct icmphdr *ich; static const size_t required_len[NR_ICMP_TYPES+1] = { [ICMP_ECHOREPLY] = 4, [ICMP_DEST_UNREACH] = 8 + sizeof(struct iphdr), [ICMP_SOURCE_QUENCH] = 8 + sizeof(struct iphdr), [ICMP_REDIRECT] = 8 + sizeof(struct iphdr), [ICMP_ECHO] = 4, [ICMP_TIME_EXCEEDED] = 8 + sizeof(struct iphdr), [ICMP_PARAMETERPROB] = 8 + sizeof(struct iphdr), [ICMP_TIMESTAMP] = 20, [ICMP_TIMESTAMPREPLY] = 20, [ICMP_ADDRESS] = 12, [ICMP_ADDRESSREPLY] = 12 }; /* Max length: 11 "PROTO=ICMP " */ sb_add(m, "PROTO=ICMP "); if (ntohs(ih->frag_off) & IP_OFFSET) break; /* Max length: 25 "INCOMPLETE [65535 bytes] " */ ich = skb_header_pointer(skb, iphoff + ih->ihl * 4, sizeof(_icmph), &_icmph); if (ich == NULL) { sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - iphoff - ih->ihl*4); break; } /* Max length: 18 "TYPE=255 CODE=255 " */ sb_add(m, "TYPE=%u CODE=%u ", ich->type, ich->code); /* Max length: 25 "INCOMPLETE [65535 bytes] " */ if (ich->type <= NR_ICMP_TYPES && required_len[ich->type] && skb->len-iphoff-ih->ihl*4 < required_len[ich->type]) { sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - iphoff - ih->ihl*4); break; } switch (ich->type) { case ICMP_ECHOREPLY: case ICMP_ECHO: /* Max length: 19 "ID=65535 SEQ=65535 " */ sb_add(m, "ID=%u SEQ=%u ", ntohs(ich->un.echo.id), ntohs(ich->un.echo.sequence)); break; case ICMP_PARAMETERPROB: /* Max length: 14 "PARAMETER=255 " */ sb_add(m, "PARAMETER=%u ", ntohl(ich->un.gateway) >> 24); break; case ICMP_REDIRECT: /* Max length: 24 "GATEWAY=255.255.255.255 " */ sb_add(m, "GATEWAY=%pI4 ", &ich->un.gateway); /* Fall through */ case ICMP_DEST_UNREACH: case ICMP_SOURCE_QUENCH: case ICMP_TIME_EXCEEDED: /* Max length: 3+maxlen */ if (!iphoff) { /* Only recurse once. */ sb_add(m, "["); dump_ipv4_packet(m, info, skb, iphoff + ih->ihl*4+sizeof(_icmph)); sb_add(m, "] "); } /* Max length: 10 "MTU=65535 " */ if (ich->type == ICMP_DEST_UNREACH && ich->code == ICMP_FRAG_NEEDED) sb_add(m, "MTU=%u ", ntohs(ich->un.frag.mtu)); } break; } /* Max Length */ case IPPROTO_AH: { struct ip_auth_hdr _ahdr; const struct ip_auth_hdr *ah; if (ntohs(ih->frag_off) & IP_OFFSET) break; /* Max length: 9 "PROTO=AH " */ sb_add(m, "PROTO=AH "); /* Max length: 25 "INCOMPLETE [65535 bytes] " */ ah = skb_header_pointer(skb, iphoff+ih->ihl*4, sizeof(_ahdr), &_ahdr); if (ah == NULL) { sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - iphoff - ih->ihl*4); break; } /* Length: 15 "SPI=0xF1234567 " */ sb_add(m, "SPI=0x%x ", ntohl(ah->spi)); break; } case IPPROTO_ESP: { struct ip_esp_hdr _esph; const struct ip_esp_hdr *eh; /* Max length: 10 "PROTO=ESP " */ sb_add(m, "PROTO=ESP "); if (ntohs(ih->frag_off) & IP_OFFSET) break; /* Max length: 25 "INCOMPLETE [65535 bytes] " */ eh = skb_header_pointer(skb, iphoff+ih->ihl*4, sizeof(_esph), &_esph); if (eh == NULL) { sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - iphoff - ih->ihl*4); break; } /* Length: 15 "SPI=0xF1234567 " */ sb_add(m, "SPI=0x%x ", ntohl(eh->spi)); break; } /* Max length: 10 "PROTO 255 " */ default: sb_add(m, "PROTO=%u ", ih->protocol); } /* Max length: 15 "UID=4294967295 " */ if ((logflags & XT_LOG_UID) && !iphoff) dump_sk_uid_gid(m, skb->sk); /* Max length: 16 "MARK=0xFFFFFFFF " */ if (!iphoff && skb->mark) sb_add(m, "MARK=0x%x ", skb->mark); /* Proto Max log string length */ /* IP: 40+46+6+11+127 = 230 */ /* TCP: 10+max(25,20+30+13+9+32+11+127) = 252 */ /* UDP: 10+max(25,20) = 35 */ /* UDPLITE: 14+max(25,20) = 39 */ /* ICMP: 11+max(25, 18+25+max(19,14,24+3+n+10,3+n+10)) = 91+n */ /* ESP: 10+max(25)+15 = 50 */ /* AH: 9+max(25)+15 = 49 */ /* unknown: 10 */ /* (ICMP allows recursion one level deep) */ /* maxlen = IP + ICMP + IP + max(TCP,UDP,ICMP,unknown) */ /* maxlen = 230+ 91 + 230 + 252 = 803 */ }
static void sb_nullterminate(CueLexer* L, StringBuffer* sb) { sb_add(L,sb,0); sb->length--; //length is now logical length, not physical length of buffer sb->terminated = 1; }
int build_update_sql(str* sql_cmd, db_cmd_t* cmd) { struct string_buffer sql_buf = {.s = NULL, .len = 0, .size = 0, .increment = 128}; db_fld_t* fld; int i, rv = 0; str tmpstr; rv = sb_add(&sql_buf, &strings[STR_UPDATE]); /* "UPDATE " */ rv |= sb_add(&sql_buf, set_str(&tmpstr, "\"")); rv |= sb_add(&sql_buf, &cmd->table); /* table name */ rv |= sb_add(&sql_buf, set_str(&tmpstr, "\"")); rv |= sb_add(&sql_buf, &strings[STR_SET]); /* " SET " */ /* column name-value pairs */ for(i = 0, fld = cmd->vals; !DB_FLD_EMPTY(fld) && !DB_FLD_LAST(fld[i]); i++) { rv |= sb_add(&sql_buf, set_str(&tmpstr, fld[i].name)); rv |= sb_add(&sql_buf, set_str(&tmpstr, "=")); rv |= sb_add(&sql_buf, &strings[STR_ESC]); if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, set_str(&tmpstr, ",")); } if (rv) goto error; if (!DB_FLD_EMPTY(cmd->match)) { rv |= sb_add(&sql_buf, &strings[STR_WHERE]); for(i = 0, fld = cmd->match; !DB_FLD_LAST(fld[i]); i++) { rv |= sb_add(&sql_buf, set_str(&tmpstr, fld[i].name)); switch(fld[i].op) { case DB_EQ: rv |= sb_add(&sql_buf, &strings[STR_OP_EQ]); break; case DB_NE: rv |= sb_add(&sql_buf, &strings[STR_OP_NE]); break; case DB_LT: rv |= sb_add(&sql_buf, &strings[STR_OP_LT]); break; case DB_GT: rv |= sb_add(&sql_buf, &strings[STR_OP_GT]); break; case DB_LEQ: rv |= sb_add(&sql_buf, &strings[STR_OP_LEQ]); break; case DB_GEQ: rv |= sb_add(&sql_buf, &strings[STR_OP_GEQ]); break; } rv |= sb_add(&sql_buf, get_marker(i + 1)); if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, &strings[STR_AND]); } } rv |= sb_add(&sql_buf, &strings[STR_ZT]); if (rv) goto error; sql_cmd->s = sql_buf.s; sql_cmd->len = sql_buf.len; return 0; error: if (sql_buf.s) pkg_free(sql_buf.s); return -1; } int build_insert_sql(str* sql_cmd, db_cmd_t* cmd) { struct string_buffer sql_buf = {.s = NULL, .len = 0, .size = 0, .increment = 128}; db_fld_t* fld; int i, rv = 0; str tmpstr; rv = sb_add(&sql_buf, &strings[STR_INSERT]); /* "INSERT INTO " */ rv |= sb_add(&sql_buf, set_str(&tmpstr, "\"")); rv |= sb_add(&sql_buf, &cmd->table); /* table name */ rv |= sb_add(&sql_buf, set_str(&tmpstr, "\" (")); /* column names */ for(i = 0, fld = cmd->vals; !DB_FLD_EMPTY(fld) && !DB_FLD_LAST(fld[i]); i++) { rv |= sb_add(&sql_buf, set_str(&tmpstr, fld[i].name)); if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, set_str(&tmpstr, ",")); } if (rv) goto error; rv |= sb_add(&sql_buf, &strings[STR_VALUES]); for(i = 0, fld = cmd->vals; !DB_FLD_EMPTY(fld) && !DB_FLD_LAST(fld[i]); i++) { rv |= sb_add(&sql_buf, get_marker(i + 1)); if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, set_str(&tmpstr, ",")); } rv |= sb_add(&sql_buf, set_str(&tmpstr, ")")); rv |= sb_add(&sql_buf, &strings[STR_ZT]); if (rv) goto error; sql_cmd->s = sql_buf.s; sql_cmd->len = sql_buf.len; return 0; error: if (sql_buf.s) pkg_free(sql_buf.s); return -1; } int build_delete_sql(str* sql_cmd, db_cmd_t* cmd) { struct string_buffer sql_buf = {.s = NULL, .len = 0, .size = 0, .increment = 128}; db_fld_t* fld; int i, rv = 0; str tmpstr; rv = sb_add(&sql_buf, &strings[STR_DELETE]); /* "DELETE FROM " */ rv |= sb_add(&sql_buf, set_str(&tmpstr, "\"")); rv |= sb_add(&sql_buf, &cmd->table); /* table name */ rv |= sb_add(&sql_buf, set_str(&tmpstr, "\"")); if (!DB_FLD_EMPTY(cmd->match)) { rv |= sb_add(&sql_buf, &strings[STR_WHERE]); for(i = 0, fld = cmd->match; !DB_FLD_LAST(fld[i]); i++) { rv |= sb_add(&sql_buf, set_str(&tmpstr, fld[i].name)); switch(fld[i].op) { case DB_EQ: rv |= sb_add(&sql_buf, &strings[STR_OP_EQ]); break; case DB_NE: rv |= sb_add(&sql_buf, &strings[STR_OP_NE]); break; case DB_LT: rv |= sb_add(&sql_buf, &strings[STR_OP_LT]); break; case DB_GT: rv |= sb_add(&sql_buf, &strings[STR_OP_GT]); break; case DB_LEQ: rv |= sb_add(&sql_buf, &strings[STR_OP_LEQ]); break; case DB_GEQ: rv |= sb_add(&sql_buf, &strings[STR_OP_GEQ]); break; } rv |= sb_add(&sql_buf, get_marker(i + 1)); if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, &strings[STR_AND]); } } rv |= sb_add(&sql_buf, &strings[STR_ZT]); if (rv) goto error; sql_cmd->s = sql_buf.s; sql_cmd->len = sql_buf.len; return 0; error: if (sql_buf.s) pkg_free(sql_buf.s); return -1; } int build_select_sql(str* sql_cmd, db_cmd_t* cmd) { struct string_buffer sql_buf = {.s = NULL, .len = 0, .size = 0, .increment = 128}; db_fld_t* fld; int i, rv = 0; str tmpstr; rv = sb_add(&sql_buf, &strings[STR_SELECT]); /* "SELECT " */ if (DB_FLD_EMPTY(cmd->result)) { rv |= sb_add(&sql_buf, set_str(&tmpstr, "*")); } else { for(i = 0, fld = cmd->result; !DB_FLD_LAST(fld[i]); i++) { rv |= sb_add(&sql_buf, set_str(&tmpstr, fld[i].name)); if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, set_str(&tmpstr, ",")); } } rv |= sb_add(&sql_buf, &strings[STR_FROM]); /* " FROM " */ rv |= sb_add(&sql_buf, set_str(&tmpstr, "\"")); rv |= sb_add(&sql_buf, &cmd->table); /* table name */ rv |= sb_add(&sql_buf, set_str(&tmpstr, "\"")); if (!DB_FLD_EMPTY(cmd->match)) { rv |= sb_add(&sql_buf, &strings[STR_WHERE]); for(i = 0, fld = cmd->match; !DB_FLD_LAST(fld[i]); i++) { rv |= sb_add(&sql_buf, set_str(&tmpstr, fld[i].name)); switch(fld[i].op) { case DB_EQ: rv |= sb_add(&sql_buf, &strings[STR_OP_EQ]); break; case DB_NE: rv |= sb_add(&sql_buf, &strings[STR_OP_NE]); break; case DB_LT: rv |= sb_add(&sql_buf, &strings[STR_OP_LT]); break; case DB_GT: rv |= sb_add(&sql_buf, &strings[STR_OP_GT]); break; case DB_LEQ: rv |= sb_add(&sql_buf, &strings[STR_OP_LEQ]); break; case DB_GEQ: rv |= sb_add(&sql_buf, &strings[STR_OP_GEQ]); break; } rv |= sb_add(&sql_buf, get_marker(i + 1)); if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, &strings[STR_AND]); } } rv |= sb_add(&sql_buf, &strings[STR_ZT]); if (rv) goto error; sql_cmd->s = sql_buf.s; sql_cmd->len = sql_buf.len; return 0; error: if (sql_buf.s) pkg_free(sql_buf.s); return -1; } int build_select_oid_sql(str* sql_cmd) { struct string_buffer sql_buf = {.s = NULL, .len = 0, .size = 0, .increment = 128}; int rv = 0; rv = sb_add(&sql_buf, &strings[STR_OID]); rv |= sb_add(&sql_buf, &strings[STR_ZT]); if (rv) goto error; sql_cmd->s = sql_buf.s; sql_cmd->len = sql_buf.len; return 0; error: if (sql_buf.s) pkg_free(sql_buf.s); return -1; } int build_timestamp_format_sql(str* sql_cmd) { struct string_buffer sql_buf = {.s = NULL, .len = 0, .size = 0, .increment = 128}; int rv = 0; rv = sb_add(&sql_buf, &strings[STR_TIMESTAMP]); rv |= sb_add(&sql_buf, &strings[STR_ZT]); if (rv) goto error; sql_cmd->s = sql_buf.s; sql_cmd->len = sql_buf.len; return 0; error: if (sql_buf.s) pkg_free(sql_buf.s); return -1; }
int main(int argc, char **argv) { int n, nfds, res; struct itimerspec timerits; struct epoll_event events[MAX_EVENTS]; struct epoll_event timerevent; IxpClient* client; struct sb sb; signals_setup(&quit_handler); struct sb_entry sbe_sda = { .sbe_path = "/rbar/60_sda", .sbe_private = "sda", .sbe_init = &init_block, .sbe_update = &update_block, .sbe_foreground = 0xbbbbbb, .sbe_background = 0x444444, .sbe_border = 0x555555, }; struct sb_entry sbe_sdb = { .sbe_path = "/rbar/61_sdb", .sbe_private = "sdb", .sbe_init = &init_block, .sbe_update = &update_block, .sbe_foreground = 0xbbbbbb, .sbe_background = 0x444444, .sbe_border = 0x555555, }; struct sb_entry sbe_sdc = { .sbe_path = "/rbar/62_sdc", .sbe_private = "sdc", .sbe_init = &init_block, .sbe_update = &update_block, .sbe_foreground = 0xbbbbbb, .sbe_background = 0x444444, .sbe_border = 0x555555, }; int epollfd = epoll_create1(EPOLL_CLOEXEC); if(epollfd == -1) { perror("epoll_create"); abort(); } int timerfd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK|TFD_CLOEXEC); if(timerfd == -1) { perror("timerfd_create"); abort(); } timerevent.events = EPOLLIN; timerevent.data.fd = timerfd; timerits.it_interval.tv_sec = 0; timerits.it_interval.tv_nsec = 250 * 1000 * 1000; timerits.it_value.tv_sec = timerits.it_interval.tv_sec; timerits.it_value.tv_nsec = timerits.it_interval.tv_nsec; client = ixp_nsmount("wmii"); if(client == NULL) { printf("ixp_nsmount: %s\n", ixp_errbuf()); abort(); } res = epoll_ctl(epollfd, EPOLL_CTL_ADD, timerfd, &timerevent); if(res == -1) { perror("epoll_ctl"); abort(); } res = timerfd_settime(timerfd, 0, &timerits, NULL); if(res == -1) { perror("timerfd_settime"); abort(); } sb_init(&sb, client); sb_add(&sb, &sbe_sda); sb_add(&sb, &sbe_sdb); sb_add(&sb, &sbe_sdc); while(1) { nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1); if(nfds == -1) { if(errno != EINTR) { perror("epoll_wait"); abort(); } } if(should_quit) { break; } for (n = 0; n < nfds; n++) { if(events[n].data.fd == timerfd) { uint64_t x; read(timerfd, &x, sizeof(x)); sb_update(&sb); } } } sb_finish(&sb); ixp_unmount(client); return 0; }
SB *sb_addstr(SB *sb, const char *s){ return sb_add(sb, s, strlen(s)); }
static int dump_tcp_header(struct sbuff *m, const struct sk_buff *skb, u8 proto, int fragment, unsigned int offset, unsigned int logflags) { struct tcphdr _tcph; const struct tcphdr *th; /* Max length: 10 "PROTO=TCP " */ sb_add(m, "PROTO=TCP "); if (fragment) return 0; /* Max length: 25 "INCOMPLETE [65535 bytes] " */ th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph); if (th == NULL) { sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - offset); return 1; } /* Max length: 20 "SPT=65535 DPT=65535 " */ sb_add(m, "SPT=%u DPT=%u ", ntohs(th->source), ntohs(th->dest)); /* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */ if (logflags & XT_LOG_TCPSEQ) sb_add(m, "SEQ=%u ACK=%u ", ntohl(th->seq), ntohl(th->ack_seq)); /* Max length: 13 "WINDOW=65535 " */ sb_add(m, "WINDOW=%u ", ntohs(th->window)); /* Max length: 9 "RES=0x3C " */ sb_add(m, "RES=0x%02x ", (u_int8_t)(ntohl(tcp_flag_word(th) & TCP_RESERVED_BITS) >> 22)); /* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */ if (th->cwr) sb_add(m, "CWR "); if (th->ece) sb_add(m, "ECE "); if (th->urg) sb_add(m, "URG "); if (th->ack) sb_add(m, "ACK "); if (th->psh) sb_add(m, "PSH "); if (th->rst) sb_add(m, "RST "); if (th->syn) sb_add(m, "SYN "); if (th->fin) sb_add(m, "FIN "); /* Max length: 11 "URGP=65535 " */ sb_add(m, "URGP=%u ", ntohs(th->urg_ptr)); if ((logflags & XT_LOG_TCPOPT) && th->doff*4 > sizeof(struct tcphdr)) { u_int8_t _opt[60 - sizeof(struct tcphdr)]; const u_int8_t *op; unsigned int i; unsigned int optsize = th->doff*4 - sizeof(struct tcphdr); op = skb_header_pointer(skb, offset + sizeof(struct tcphdr), optsize, _opt); if (op == NULL) { sb_add(m, "OPT (TRUNCATED)"); return 1; } /* Max length: 127 "OPT (" 15*4*2chars ") " */ sb_add(m, "OPT ("); for (i = 0; i < optsize; i++) sb_add(m, "%02X", op[i]); sb_add(m, ") "); } return 0; }
/* One level of recursion won't kill us */ static void dump_packet(struct sbuff *m, const struct nf_loginfo *info, const struct sk_buff *skb, unsigned int ip6hoff, int recurse) { u_int8_t currenthdr; int fragment; struct ipv6hdr _ip6h, *ih; unsigned int ptr; unsigned int hdrlen = 0; unsigned int logflags; if (info->type == NF_LOG_TYPE_LOG) logflags = info->u.log.logflags; else logflags = NF_LOG_MASK; ih = skb_header_pointer(skb, ip6hoff, sizeof(_ip6h), &_ip6h); if (ih == NULL) { sb_add(m, "TRUNCATED"); return; } /* Max length: 88 "SRC=0000.0000.0000.0000.0000.0000.0000.0000 DST=0000.0000.0000.0000.0000.0000.0000.0000 " */ sb_add(m, "SRC=" NIP6_FMT " DST=" NIP6_FMT " ", NIP6(ih->saddr), NIP6(ih->daddr)); /* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */ sb_add(m, "LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ", ntohs(ih->payload_len) + sizeof(struct ipv6hdr), (ntohl(*(__be32 *)ih) & 0x0ff00000) >> 20, ih->hop_limit, (ntohl(*(__be32 *)ih) & 0x000fffff)); fragment = 0; ptr = ip6hoff + sizeof(struct ipv6hdr); currenthdr = ih->nexthdr; while (currenthdr != NEXTHDR_NONE && ip6t_ext_hdr(currenthdr)) { struct ipv6_opt_hdr _hdr, *hp; hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); if (hp == NULL) { sb_add(m, "TRUNCATED"); return; } /* Max length: 48 "OPT (...) " */ if (logflags & IP6T_LOG_IPOPT) sb_add(m, "OPT ( "); switch (currenthdr) { case IPPROTO_FRAGMENT: { struct frag_hdr _fhdr, *fh; sb_add(m, "FRAG:"); fh = skb_header_pointer(skb, ptr, sizeof(_fhdr), &_fhdr); if (fh == NULL) { sb_add(m, "TRUNCATED "); return; } /* Max length: 6 "65535 " */ sb_add(m, "%u ", ntohs(fh->frag_off) & 0xFFF8); /* Max length: 11 "INCOMPLETE " */ if (fh->frag_off & htons(0x0001)) sb_add(m, "INCOMPLETE "); sb_add(m, "ID:%08x ", ntohl(fh->identification)); if (ntohs(fh->frag_off) & 0xFFF8) fragment = 1; hdrlen = 8; break; } case IPPROTO_DSTOPTS: case IPPROTO_ROUTING: case IPPROTO_HOPOPTS: if (fragment) { if (logflags & IP6T_LOG_IPOPT) sb_add(m, ")"); return; } hdrlen = ipv6_optlen(hp); break; /* Max Length */ case IPPROTO_AH: if (logflags & IP6T_LOG_IPOPT) { struct ip_auth_hdr _ahdr, *ah; /* Max length: 3 "AH " */ sb_add(m, "AH "); if (fragment) { sb_add(m, ")"); return; } ah = skb_header_pointer(skb, ptr, sizeof(_ahdr), &_ahdr); if (ah == NULL) { /* * Max length: 26 "INCOMPLETE [65535 * bytes] )" */ sb_add(m, "INCOMPLETE [%u bytes] )", skb->len - ptr); return; } /* Length: 15 "SPI=0xF1234567 */ sb_add(m, "SPI=0x%x ", ntohl(ah->spi)); } hdrlen = (hp->hdrlen+2)<<2; break; case IPPROTO_ESP: if (logflags & IP6T_LOG_IPOPT) { struct ip_esp_hdr _esph, *eh; /* Max length: 4 "ESP " */ sb_add(m, "ESP "); if (fragment) { sb_add(m, ")"); return; } /* * Max length: 26 "INCOMPLETE [65535 bytes] )" */ eh = skb_header_pointer(skb, ptr, sizeof(_esph), &_esph); if (eh == NULL) { sb_add(m, "INCOMPLETE [%u bytes] )", skb->len - ptr); return; } /* Length: 16 "SPI=0xF1234567 )" */ sb_add(m, "SPI=0x%x )", ntohl(eh->spi) ); } return; default: /* Max length: 20 "Unknown Ext Hdr 255" */ sb_add(m, "Unknown Ext Hdr %u", currenthdr); return; } if (logflags & IP6T_LOG_IPOPT) sb_add(m, ") "); currenthdr = hp->nexthdr; ptr += hdrlen; } switch (currenthdr) { case IPPROTO_TCP: { struct tcphdr _tcph, *th; /* Max length: 10 "PROTO=TCP " */ sb_add(m, "PROTO=TCP "); if (fragment) break; /* Max length: 25 "INCOMPLETE [65535 bytes] " */ th = skb_header_pointer(skb, ptr, sizeof(_tcph), &_tcph); if (th == NULL) { sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - ptr); return; } /* Max length: 20 "SPT=65535 DPT=65535 " */ sb_add(m, "SPT=%u DPT=%u ", ntohs(th->source), ntohs(th->dest)); /* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */ if (logflags & IP6T_LOG_TCPSEQ) sb_add(m, "SEQ=%u ACK=%u ", ntohl(th->seq), ntohl(th->ack_seq)); /* Max length: 13 "WINDOW=65535 " */ sb_add(m, "WINDOW=%u ", ntohs(th->window)); /* Max length: 9 "RES=0x3C " */ sb_add(m, "RES=0x%02x ", (u_int8_t)(ntohl(tcp_flag_word(th) & TCP_RESERVED_BITS) >> 22)); /* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */ if (th->cwr) sb_add(m, "CWR "); if (th->ece) sb_add(m, "ECE "); if (th->urg) sb_add(m, "URG "); if (th->ack) sb_add(m, "ACK "); if (th->psh) sb_add(m, "PSH "); if (th->rst) sb_add(m, "RST "); if (th->syn) sb_add(m, "SYN "); if (th->fin) sb_add(m, "FIN "); /* Max length: 11 "URGP=65535 " */ sb_add(m, "URGP=%u ", ntohs(th->urg_ptr)); if ((logflags & IP6T_LOG_TCPOPT) && th->doff * 4 > sizeof(struct tcphdr)) { u_int8_t _opt[60 - sizeof(struct tcphdr)], *op; unsigned int i; unsigned int optsize = th->doff * 4 - sizeof(struct tcphdr); op = skb_header_pointer(skb, ptr + sizeof(struct tcphdr), optsize, _opt); if (op == NULL) { sb_add(m, "OPT (TRUNCATED)"); return; } /* Max length: 127 "OPT (" 15*4*2chars ") " */ sb_add(m, "OPT ("); for (i =0; i < optsize; i++) sb_add(m, "%02X", op[i]); sb_add(m, ") "); } break; } case IPPROTO_UDP: case IPPROTO_UDPLITE: { struct udphdr _udph, *uh; if (currenthdr == IPPROTO_UDP) /* Max length: 10 "PROTO=UDP " */ sb_add(m, "PROTO=UDP " ); else /* Max length: 14 "PROTO=UDPLITE " */ sb_add(m, "PROTO=UDPLITE "); if (fragment) break; /* Max length: 25 "INCOMPLETE [65535 bytes] " */ uh = skb_header_pointer(skb, ptr, sizeof(_udph), &_udph); if (uh == NULL) { sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - ptr); return; } /* Max length: 20 "SPT=65535 DPT=65535 " */ sb_add(m, "SPT=%u DPT=%u LEN=%u ", ntohs(uh->source), ntohs(uh->dest), ntohs(uh->len)); break; } case IPPROTO_ICMPV6: { struct icmp6hdr _icmp6h, *ic; /* Max length: 13 "PROTO=ICMPv6 " */ sb_add(m, "PROTO=ICMPv6 "); if (fragment) break; /* Max length: 25 "INCOMPLETE [65535 bytes] " */ ic = skb_header_pointer(skb, ptr, sizeof(_icmp6h), &_icmp6h); if (ic == NULL) { sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - ptr); return; } /* Max length: 18 "TYPE=255 CODE=255 " */ sb_add(m, "TYPE=%u CODE=%u ", ic->icmp6_type, ic->icmp6_code); switch (ic->icmp6_type) { case ICMPV6_ECHO_REQUEST: case ICMPV6_ECHO_REPLY: /* Max length: 19 "ID=65535 SEQ=65535 " */ sb_add(m, "ID=%u SEQ=%u ", ntohs(ic->icmp6_identifier), ntohs(ic->icmp6_sequence)); break; case ICMPV6_MGM_QUERY: case ICMPV6_MGM_REPORT: case ICMPV6_MGM_REDUCTION: break; case ICMPV6_PARAMPROB: /* Max length: 17 "POINTER=ffffffff " */ sb_add(m, "POINTER=%08x ", ntohl(ic->icmp6_pointer)); /* Fall through */ case ICMPV6_DEST_UNREACH: case ICMPV6_PKT_TOOBIG: case ICMPV6_TIME_EXCEED: /* Max length: 3+maxlen */ if (recurse) { sb_add(m, "["); dump_packet(m, info, skb, ptr + sizeof(_icmp6h), 0); sb_add(m, "] "); } /* Max length: 10 "MTU=65535 " */ if (ic->icmp6_type == ICMPV6_PKT_TOOBIG) sb_add(m, "MTU=%u ", ntohl(ic->icmp6_mtu)); } break; } /* Max length: 10 "PROTO=255 " */ default: sb_add(m, "PROTO=%u ", currenthdr); } /* Max length: 15 "UID=4294967295 " */ if ((logflags & IP6T_LOG_UID) && recurse && skb->sk) { read_lock_bh(&skb->sk->sk_callback_lock); if (skb->sk->sk_socket && skb->sk->sk_socket->file) sb_add(m, "UID=%u GID=%u ", skb->sk->sk_socket->file->f_uid, skb->sk->sk_socket->file->f_gid); read_unlock_bh(&skb->sk->sk_callback_lock); } /* Max length: 16 "MARK=0xFFFFFFFF " */ if (!recurse && skb->mark) sb_add(m, "MARK=0x%x ", skb->mark); }
int ld_prepare_ldap_filter(char** filter, db_cmd_t* cmd, str* add) { db_fld_t* fld; struct ld_fld* lfld; int rv = 0; struct sbuf buf = { .s = NULL, .len = 0, .size = 0, .increment = 128 }; fld = cmd->match; skip_client_side_filtering_fields(cmd, &fld); /* Return NULL if there are no fields and no preconfigured search * string supplied in the configuration file */ if ((DB_FLD_EMPTY(fld) || DB_FLD_LAST(*fld)) && ((add->s == NULL) || !add->len)) { *filter = NULL; return 0; } rv = sb_add(&buf, "(&", 2); if (add->s && add->len) { /* Add the filter component specified in the config file */ rv |= sb_add(&buf, add->s, add->len); } for(; !DB_FLD_EMPTY(fld) && !DB_FLD_LAST(*fld); fld++, skip_client_side_filtering_fields(cmd, &fld)) { int op; lfld = DB_GET_PAYLOAD(fld); op = fld->op; if (fld->flags & DB_NULL) { switch (op) { case DB_EQ: /* fld==NULL -> (!(x=*)) */ op = DB_NE; case DB_NE: /* fld!=NULL -> (x=*) */ op = DB_EQ; break; default: ERR("ldap: Cannot compare null value field %s\n", fld->name); goto error; } } /* we need construct operators as: not: (!(fld=val)) </>: (!(fld=val))(fld</>val) */ switch (op) { case DB_LT: case DB_GT: case DB_NE: rv |= sb_add(&buf, "(!(", 3); rv |= sb_add(&buf, lfld->attr.s, lfld->attr.len); rv |= sb_add(&buf, "=", 1); if (fld->flags & DB_NULL) { rv |= sb_add(&buf, "*", 1); } else { if (ld_db2ldap(&buf, fld) < 0) { goto error; } } rv |= sb_add(&buf, "))", 2); break; default: ; } if (op != DB_NE) { rv |= sb_add(&buf, "(", 1); rv |= sb_add(&buf, lfld->attr.s, lfld->attr.len); switch (op) { case DB_LEQ: case DB_LT: rv |= sb_add(&buf, "<=", 2); break; case DB_GEQ: case DB_GT: rv |= sb_add(&buf, ">=", 2); break; case DB_EQ: rv |= sb_add(&buf, "=", 1); break; default: ; } if (fld->flags & DB_NULL) { rv |= sb_add(&buf, "*", 1); } else { if (ld_db2ldap(&buf, fld) < 0) { goto error; } } rv |= sb_add(&buf, ")", 1); } } rv |= sb_add(&buf, ")", 1); rv |= sb_add(&buf, "", 1); if (rv) goto error; *filter = buf.s; return 0; error: if (buf.s) pkg_free(buf.s); return -1; }
/* One level of recursion won't kill us */ static void dump_ipv6_packet(struct sbuff *m, const struct nf_loginfo *info, const struct sk_buff *skb, unsigned int ip6hoff, int recurse) { u_int8_t currenthdr; int fragment; struct ipv6hdr _ip6h; const struct ipv6hdr *ih; unsigned int ptr; unsigned int hdrlen = 0; unsigned int logflags; if (info->type == NF_LOG_TYPE_LOG) logflags = info->u.log.logflags; else logflags = NF_LOG_MASK; ih = skb_header_pointer(skb, ip6hoff, sizeof(_ip6h), &_ip6h); if (ih == NULL) { sb_add(m, "TRUNCATED"); return; } /* Max length: 88 "SRC=0000.0000.0000.0000.0000.0000.0000.0000 DST=0000.0000.0000.0000.0000.0000.0000.0000 " */ sb_add(m, "SRC=%pI6 DST=%pI6 ", &ih->saddr, &ih->daddr); /* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */ sb_add(m, "LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ", ntohs(ih->payload_len) + sizeof(struct ipv6hdr), (ntohl(*(__be32 *)ih) & 0x0ff00000) >> 20, ih->hop_limit, (ntohl(*(__be32 *)ih) & 0x000fffff)); fragment = 0; ptr = ip6hoff + sizeof(struct ipv6hdr); currenthdr = ih->nexthdr; while (currenthdr != NEXTHDR_NONE && ip6t_ext_hdr(currenthdr)) { struct ipv6_opt_hdr _hdr; const struct ipv6_opt_hdr *hp; hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); if (hp == NULL) { sb_add(m, "TRUNCATED"); return; } /* Max length: 48 "OPT (...) " */ if (logflags & XT_LOG_IPOPT) sb_add(m, "OPT ( "); switch (currenthdr) { case IPPROTO_FRAGMENT: { struct frag_hdr _fhdr; const struct frag_hdr *fh; sb_add(m, "FRAG:"); fh = skb_header_pointer(skb, ptr, sizeof(_fhdr), &_fhdr); if (fh == NULL) { sb_add(m, "TRUNCATED "); return; } /* Max length: 6 "65535 " */ sb_add(m, "%u ", ntohs(fh->frag_off) & 0xFFF8); /* Max length: 11 "INCOMPLETE " */ if (fh->frag_off & htons(0x0001)) sb_add(m, "INCOMPLETE "); sb_add(m, "ID:%08x ", ntohl(fh->identification)); if (ntohs(fh->frag_off) & 0xFFF8) fragment = 1; hdrlen = 8; break; } case IPPROTO_DSTOPTS: case IPPROTO_ROUTING: case IPPROTO_HOPOPTS: if (fragment) { if (logflags & XT_LOG_IPOPT) sb_add(m, ")"); return; } hdrlen = ipv6_optlen(hp); break; /* Max Length */ case IPPROTO_AH: if (logflags & XT_LOG_IPOPT) { struct ip_auth_hdr _ahdr; const struct ip_auth_hdr *ah; /* Max length: 3 "AH " */ sb_add(m, "AH "); if (fragment) { sb_add(m, ")"); return; } ah = skb_header_pointer(skb, ptr, sizeof(_ahdr), &_ahdr); if (ah == NULL) { /* * Max length: 26 "INCOMPLETE [65535 * bytes] )" */ sb_add(m, "INCOMPLETE [%u bytes] )", skb->len - ptr); return; } /* Length: 15 "SPI=0xF1234567 */ sb_add(m, "SPI=0x%x ", ntohl(ah->spi)); } hdrlen = (hp->hdrlen+2)<<2; break; case IPPROTO_ESP: if (logflags & XT_LOG_IPOPT) { struct ip_esp_hdr _esph; const struct ip_esp_hdr *eh; /* Max length: 4 "ESP " */ sb_add(m, "ESP "); if (fragment) { sb_add(m, ")"); return; } /* * Max length: 26 "INCOMPLETE [65535 bytes] )" */ eh = skb_header_pointer(skb, ptr, sizeof(_esph), &_esph); if (eh == NULL) { sb_add(m, "INCOMPLETE [%u bytes] )", skb->len - ptr); return; } /* Length: 16 "SPI=0xF1234567 )" */ sb_add(m, "SPI=0x%x )", ntohl(eh->spi)); } return; default: /* Max length: 20 "Unknown Ext Hdr 255" */ sb_add(m, "Unknown Ext Hdr %u", currenthdr); return; } if (logflags & XT_LOG_IPOPT) sb_add(m, ") "); currenthdr = hp->nexthdr; ptr += hdrlen; } switch (currenthdr) { case IPPROTO_TCP: if (dump_tcp_header(m, skb, currenthdr, fragment, ptr, logflags)) return; break; case IPPROTO_UDP: case IPPROTO_UDPLITE: if (dump_udp_header(m, skb, currenthdr, fragment, ptr)) return; break; case IPPROTO_ICMPV6: { struct icmp6hdr _icmp6h; const struct icmp6hdr *ic; /* Max length: 13 "PROTO=ICMPv6 " */ sb_add(m, "PROTO=ICMPv6 "); if (fragment) break; /* Max length: 25 "INCOMPLETE [65535 bytes] " */ ic = skb_header_pointer(skb, ptr, sizeof(_icmp6h), &_icmp6h); if (ic == NULL) { sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - ptr); return; } /* Max length: 18 "TYPE=255 CODE=255 " */ sb_add(m, "TYPE=%u CODE=%u ", ic->icmp6_type, ic->icmp6_code); switch (ic->icmp6_type) { case ICMPV6_ECHO_REQUEST: case ICMPV6_ECHO_REPLY: /* Max length: 19 "ID=65535 SEQ=65535 " */ sb_add(m, "ID=%u SEQ=%u ", ntohs(ic->icmp6_identifier), ntohs(ic->icmp6_sequence)); break; case ICMPV6_MGM_QUERY: case ICMPV6_MGM_REPORT: case ICMPV6_MGM_REDUCTION: break; case ICMPV6_PARAMPROB: /* Max length: 17 "POINTER=ffffffff " */ sb_add(m, "POINTER=%08x ", ntohl(ic->icmp6_pointer)); /* Fall through */ case ICMPV6_DEST_UNREACH: case ICMPV6_PKT_TOOBIG: case ICMPV6_TIME_EXCEED: /* Max length: 3+maxlen */ if (recurse) { sb_add(m, "["); dump_ipv6_packet(m, info, skb, ptr + sizeof(_icmp6h), 0); sb_add(m, "] "); } /* Max length: 10 "MTU=65535 " */ if (ic->icmp6_type == ICMPV6_PKT_TOOBIG) sb_add(m, "MTU=%u ", ntohl(ic->icmp6_mtu)); } break; } /* Max length: 10 "PROTO=255 " */ default: sb_add(m, "PROTO=%u ", currenthdr); } /* Max length: 15 "UID=4294967295 " */ if ((logflags & XT_LOG_UID) && recurse) dump_sk_uid_gid(m, skb->sk); /* Max length: 16 "MARK=0xFFFFFFFF " */ if (!recurse && skb->mark) sb_add(m, "MARK=0x%x ", skb->mark); }
/* One level of recursion won't kill us */ static void dump_packet(struct sbuff *m, const struct nf_loginfo *info, const struct sk_buff *skb, unsigned int iphoff) { struct iphdr _iph, *ih; unsigned int logflags; if (info->type == NF_LOG_TYPE_LOG) logflags = info->u.log.logflags; else logflags = NF_LOG_MASK; ih = skb_header_pointer(skb, iphoff, sizeof(_iph), &_iph); if (ih == NULL) { sb_add(m, "TRUNCATED"); return; } /* Important fields: * TOS, len, DF/MF, fragment offset, TTL, src, dst, options. */ /* Max length: 40 "SRC=255.255.255.255 DST=255.255.255.255 " */ sb_add(m, "SRC=%u.%u.%u.%u DST=%u.%u.%u.%u ", NIPQUAD(ih->saddr), NIPQUAD(ih->daddr)); /* Max length: 46 "LEN=65535 TOS=0xFF PREC=0xFF TTL=255 ID=65535 " */ sb_add(m, "LEN=%u TOS=0x%02X PREC=0x%02X TTL=%u ID=%u ", ntohs(ih->tot_len), ih->tos & IPTOS_TOS_MASK, ih->tos & IPTOS_PREC_MASK, ih->ttl, ntohs(ih->id)); /* Max length: 6 "CE DF MF " */ if (ntohs(ih->frag_off) & IP_CE) sb_add(m, "CE "); if (ntohs(ih->frag_off) & IP_DF) sb_add(m, "DF "); if (ntohs(ih->frag_off) & IP_MF) sb_add(m, "MF "); /* Max length: 11 "FRAG:65535 " */ if (ntohs(ih->frag_off) & IP_OFFSET) sb_add(m, "FRAG:%u ", ntohs(ih->frag_off) & IP_OFFSET); if ((logflags & IPT_LOG_IPOPT) && ih->ihl * 4 > sizeof(struct iphdr)) { unsigned char _opt[4 * 15 - sizeof(struct iphdr)], *op; unsigned int i, optsize; optsize = ih->ihl * 4 - sizeof(struct iphdr); op = skb_header_pointer(skb, iphoff+sizeof(_iph), optsize, _opt); if (op == NULL) { sb_add(m, "TRUNCATED"); return; } /* Max length: 127 "OPT (" 15*4*2chars ") " */ sb_add(m, "OPT ("); for (i = 0; i < optsize; i++) sb_add(m, "%02X", op[i]); sb_add(m, ") "); } switch (ih->protocol) { case IPPROTO_TCP: { struct tcphdr _tcph, *th; /* Max length: 10 "PROTO=TCP " */ sb_add(m, "PROTO=TCP "); if (ntohs(ih->frag_off) & IP_OFFSET) break; /* Max length: 25 "INCOMPLETE [65535 bytes] " */ th = skb_header_pointer(skb, iphoff + ih->ihl * 4, sizeof(_tcph), &_tcph); if (th == NULL) { sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - iphoff - ih->ihl*4); break; } /* Max length: 20 "SPT=65535 DPT=65535 " */ sb_add(m, "SPT=%u DPT=%u ", ntohs(th->source), ntohs(th->dest)); /* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */ if (logflags & IPT_LOG_TCPSEQ) sb_add(m, "SEQ=%u ACK=%u ", ntohl(th->seq), ntohl(th->ack_seq)); /* Max length: 13 "WINDOW=65535 " */ sb_add(m, "WINDOW=%u ", ntohs(th->window)); /* Max length: 9 "RES=0x3F " */ sb_add(m, "RES=0x%02x ", (u8)(ntohl(tcp_flag_word(th) & TCP_RESERVED_BITS) >> 22)); /* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */ if (th->cwr) sb_add(m, "CWR "); if (th->ece) sb_add(m, "ECE "); if (th->urg) sb_add(m, "URG "); if (th->ack) sb_add(m, "ACK "); if (th->psh) sb_add(m, "PSH "); if (th->rst) sb_add(m, "RST "); if (th->syn) sb_add(m, "SYN "); if (th->fin) sb_add(m, "FIN "); /* Max length: 11 "URGP=65535 " */ sb_add(m, "URGP=%u ", ntohs(th->urg_ptr)); if ((logflags & IPT_LOG_TCPOPT) && th->doff * 4 > sizeof(struct tcphdr)) { unsigned char _opt[4 * 15 - sizeof(struct tcphdr)]; unsigned char *op; unsigned int i, optsize; optsize = th->doff * 4 - sizeof(struct tcphdr); op = skb_header_pointer(skb, iphoff+ih->ihl*4+sizeof(_tcph), optsize, _opt); if (op == NULL) { sb_add(m, "TRUNCATED"); return; } /* Max length: 127 "OPT (" 15*4*2chars ") " */ sb_add(m, "OPT ("); for (i = 0; i < optsize; i++) sb_add(m, "%02X", op[i]); sb_add(m, ") "); } break; } case IPPROTO_UDP: case IPPROTO_UDPLITE: { struct udphdr _udph, *uh; if (ih->protocol == IPPROTO_UDP) /* Max length: 10 "PROTO=UDP " */ sb_add(m, "PROTO=UDP " ); else /* Max length: 14 "PROTO=UDPLITE " */ sb_add(m, "PROTO=UDPLITE "); if (ntohs(ih->frag_off) & IP_OFFSET) break; /* Max length: 25 "INCOMPLETE [65535 bytes] " */ uh = skb_header_pointer(skb, iphoff+ih->ihl*4, sizeof(_udph), &_udph); if (uh == NULL) { sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - iphoff - ih->ihl*4); break; } /* Max length: 20 "SPT=65535 DPT=65535 " */ sb_add(m, "SPT=%u DPT=%u LEN=%u ", ntohs(uh->source), ntohs(uh->dest), ntohs(uh->len)); break; } case IPPROTO_ICMP: { struct icmphdr _icmph, *ich; static const size_t required_len[NR_ICMP_TYPES+1] = { [ICMP_ECHOREPLY] = 4, [ICMP_DEST_UNREACH] = 8 + sizeof(struct iphdr), [ICMP_SOURCE_QUENCH] = 8 + sizeof(struct iphdr), [ICMP_REDIRECT] = 8 + sizeof(struct iphdr), [ICMP_ECHO] = 4, [ICMP_TIME_EXCEEDED] = 8 + sizeof(struct iphdr), [ICMP_PARAMETERPROB] = 8 + sizeof(struct iphdr), [ICMP_TIMESTAMP] = 20, [ICMP_TIMESTAMPREPLY] = 20, [ICMP_ADDRESS] = 12, [ICMP_ADDRESSREPLY] = 12 }; /* Max length: 11 "PROTO=ICMP " */ sb_add(m, "PROTO=ICMP "); if (ntohs(ih->frag_off) & IP_OFFSET) break; /* Max length: 25 "INCOMPLETE [65535 bytes] " */ ich = skb_header_pointer(skb, iphoff + ih->ihl * 4, sizeof(_icmph), &_icmph); if (ich == NULL) { sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - iphoff - ih->ihl*4); break; } /* Max length: 18 "TYPE=255 CODE=255 " */ sb_add(m, "TYPE=%u CODE=%u ", ich->type, ich->code); /* Max length: 25 "INCOMPLETE [65535 bytes] " */ if (ich->type <= NR_ICMP_TYPES && required_len[ich->type] && skb->len-iphoff-ih->ihl*4 < required_len[ich->type]) { sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - iphoff - ih->ihl*4); break; } switch (ich->type) { case ICMP_ECHOREPLY: case ICMP_ECHO: /* Max length: 19 "ID=65535 SEQ=65535 " */ sb_add(m, "ID=%u SEQ=%u ", ntohs(ich->un.echo.id), ntohs(ich->un.echo.sequence)); break; case ICMP_PARAMETERPROB: /* Max length: 14 "PARAMETER=255 " */ sb_add(m, "PARAMETER=%u ", ntohl(ich->un.gateway) >> 24); break; case ICMP_REDIRECT: /* Max length: 24 "GATEWAY=255.255.255.255 " */ sb_add(m, "GATEWAY=%u.%u.%u.%u ", NIPQUAD(ich->un.gateway)); /* Fall through */ case ICMP_DEST_UNREACH: case ICMP_SOURCE_QUENCH: case ICMP_TIME_EXCEEDED: /* Max length: 3+maxlen */ if (!iphoff) { /* Only recurse once. */ sb_add(m, "["); dump_packet(m, info, skb, iphoff + ih->ihl*4+sizeof(_icmph)); sb_add(m, "] "); } /* Max length: 10 "MTU=65535 " */ if (ich->type == ICMP_DEST_UNREACH && ich->code == ICMP_FRAG_NEEDED) sb_add(m, "MTU=%u ", ntohs(ich->un.frag.mtu)); } break; } /* Max Length */ case IPPROTO_AH: { struct ip_auth_hdr _ahdr, *ah; if (ntohs(ih->frag_off) & IP_OFFSET) break; /* Max length: 9 "PROTO=AH " */ sb_add(m, "PROTO=AH "); /* Max length: 25 "INCOMPLETE [65535 bytes] " */ ah = skb_header_pointer(skb, iphoff+ih->ihl*4, sizeof(_ahdr), &_ahdr); if (ah == NULL) { sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - iphoff - ih->ihl*4); break; } /* Length: 15 "SPI=0xF1234567 " */ sb_add(m, "SPI=0x%x ", ntohl(ah->spi)); break; } case IPPROTO_ESP: { struct ip_esp_hdr _esph, *eh; /* Max length: 10 "PROTO=ESP " */ sb_add(m, "PROTO=ESP "); if (ntohs(ih->frag_off) & IP_OFFSET) break; /* Max length: 25 "INCOMPLETE [65535 bytes] " */ eh = skb_header_pointer(skb, iphoff+ih->ihl*4, sizeof(_esph), &_esph); if (eh == NULL) { sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - iphoff - ih->ihl*4); break; } /* Length: 15 "SPI=0xF1234567 " */ sb_add(m, "SPI=0x%x ", ntohl(eh->spi)); break; } /* Max length: 10 "PROTO 255 " */ default: sb_add(m, "PROTO=%u ", ih->protocol); } /* Max length: 15 "UID=4294967295 " */ if ((logflags & IPT_LOG_UID) && !iphoff && skb->sk) { read_lock_bh(&skb->sk->sk_callback_lock); if (skb->sk->sk_socket && skb->sk->sk_socket->file) sb_add(m, "UID=%u GID=%u ", skb->sk->sk_socket->file->f_uid, skb->sk->sk_socket->file->f_gid); read_unlock_bh(&skb->sk->sk_callback_lock); } /* Max length: 16 "MARK=0xFFFFFFFF " */ if (!iphoff && skb->mark) sb_add(m, "MARK=0x%x ", skb->mark); /* Proto Max log string length */ /* IP: 40+46+6+11+127 = 230 */ /* TCP: 10+max(25,20+30+13+9+32+11+127) = 252 */ /* UDP: 10+max(25,20) = 35 */ /* UDPLITE: 14+max(25,20) = 39 */ /* ICMP: 11+max(25, 18+25+max(19,14,24+3+n+10,3+n+10)) = 91+n */ /* ESP: 10+max(25)+15 = 50 */ /* AH: 9+max(25)+15 = 49 */ /* unknown: 10 */ /* (ICMP allows recursion one level deep) */ /* maxlen = IP + ICMP + IP + max(TCP,UDP,ICMP,unknown) */ /* maxlen = 230+ 91 + 230 + 252 = 803 */ }
/** * Builds UPDATE statement where cmd->valss specify column name-value pairs * and cmd->match specify WHERE clause. * @param sql_cmd SQL statement as a result of this function * @param cmd input for statement creation */ static int build_update_cmd(str* sql_cmd, db_cmd_t* cmd) { struct string_buffer sql_buf = {.s = NULL, .len = 0, .size = 0, .increment = 128}; db_fld_t* fld; int i; int rv = 0; str tmpstr; rv = sb_add(&sql_buf, &strings[STR_UPDATE]); /* "UPDATE " */ rv |= sb_add(&sql_buf, &cmd->table); /* table name */ rv |= sb_add(&sql_buf, &strings[STR_SET]); /* " SET " */ /* column name-value pairs */ for(i = 0, fld = cmd->vals; !DB_FLD_LAST(fld[i]); i++) { rv |= sb_add(&sql_buf, set_str(&tmpstr, fld[i].name)); rv |= sb_add(&sql_buf, set_str(&tmpstr, " = ")); rv |= sb_add(&sql_buf, &strings[STR_ESC]); if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, set_str(&tmpstr, ", ")); } if (rv) { goto err; } if (!DB_FLD_EMPTY(cmd->match)) { rv |= sb_add(&sql_buf, &strings[STR_WHERE]); for(i = 0, fld = cmd->match; !DB_FLD_LAST(fld[i]); i++) { rv |= sb_add(&sql_buf, set_str(&tmpstr, fld[i].name)); switch(fld[i].op) { case DB_EQ: rv |= sb_add(&sql_buf, &strings[STR_OP_EQ]); break; case DB_NE: rv |= sb_add(&sql_buf, &strings[STR_OP_NE]); break; case DB_LT: rv |= sb_add(&sql_buf, &strings[STR_OP_LT]); break; case DB_GT: rv |= sb_add(&sql_buf, &strings[STR_OP_GT]); break; case DB_LEQ: rv |= sb_add(&sql_buf, &strings[STR_OP_LEQ]); break; case DB_GEQ: rv |= sb_add(&sql_buf, &strings[STR_OP_GEQ]); break; } rv |= sb_add(&sql_buf, &strings[STR_ESC]); if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, &strings[STR_AND]); } } rv |= sb_add(&sql_buf, set_str(&tmpstr, "\0")); if (rv) { goto err; } sql_cmd->s = sql_buf.s; sql_cmd->len = sql_buf.len; return 0; err: if (sql_buf.s) pkg_free(sql_buf.s); return -1; } static inline void update_field(MYSQL_BIND *param, db_fld_t* fld) { struct my_fld* fp; /* field payload */ struct tm* t; fp = DB_GET_PAYLOAD(fld); #ifndef MYSQL_FAKE_NULL fp->is_null = fld->flags & DB_NULL; if (fp->is_null) return; #else if (fld->flags & DB_NULL) { switch(fld->type) { case DB_STR: case DB_CSTR: param->buffer = FAKE_NULL_STR.s; fp->length = FAKE_NULL_STR.len; break; case DB_INT: *(int*)param->buffer = FAKE_NULL_INT; break; case DB_BLOB: case DB_DATETIME: case DB_NONE: case DB_FLOAT: case DB_DOUBLE: case DB_BITMAP: /* we don't have fake null value for these types */ fp->is_null = DB_NULL; break; } return; } #endif switch(fld->type) { case DB_STR: param->buffer = fld->v.lstr.s; fp->length = fld->v.lstr.len; break; case DB_BLOB: param->buffer = fld->v.blob.s; fp->length = fld->v.blob.len; break; case DB_CSTR: param->buffer = (char*)fld->v.cstr; fp->length = strlen(fld->v.cstr); break; case DB_DATETIME: t = gmtime(&fld->v.time); fp->time.second = t->tm_sec; fp->time.minute = t->tm_min; fp->time.hour = t->tm_hour; fp->time.day = t->tm_mday; fp->time.month = t->tm_mon + 1; fp->time.year = t->tm_year + 1900; break; case DB_NONE: case DB_INT: case DB_FLOAT: case DB_DOUBLE: case DB_BITMAP: /* No need to do anything for these types */ break; } } /** * Update values of MySQL bound parameters with values from * the DB API. * @param cmd Command structure which contains pointers to MYSQL_STMT and parameters values * @see bind_mysql_params */ static inline void set_mysql_params(db_cmd_t* cmd) { struct my_cmd* mcmd; int i; mcmd = DB_GET_PAYLOAD(cmd); /* FIXME: We are updating internals of the prepared statement here, * this is probably not nice but I could not find another way of * updating the pointer to the buffer without the need to run * mysql_stmt_bind_param again (which would be innefficient) */ for(i = 0; i < cmd->vals_count; i++) { update_field(mcmd->st->params + i, cmd->vals + i); } for(i = 0; i < cmd->match_count; i++) { update_field(mcmd->st->params + cmd->vals_count + i, cmd->match + i); } } static inline int update_result(db_fld_t* result, MYSQL_STMT* st) { int i; struct my_fld* rp; /* Payload of the current field in result */ struct tm t; /* Iterate through all the fields returned by MySQL and convert * them to DB API representation if necessary */ for(i = 0; i < st->field_count; i++) { rp = DB_GET_PAYLOAD(result + i); if (rp->is_null) { result[i].flags |= DB_NULL; continue; } else { result[i].flags &= ~DB_NULL; } switch(result[i].type) { case DB_STR: result[i].v.lstr.len = rp->length; #ifdef MYSQL_FAKE_NULL if (STR_EQ(FAKE_NULL_STR,result[i].v.lstr)) { result[i].flags |= DB_NULL; } #endif break; case DB_BLOB: result[i].v.blob.len = rp->length; break; case DB_CSTR: if (rp->length < STR_BUF_SIZE) { result[i].v.cstr[rp->length] = '\0'; } else { /* Truncated field but rp->length contains full size, * zero terminated the last byte in the buffer */ result[i].v.cstr[STR_BUF_SIZE - 1] = '\0'; } #ifdef MYSQL_FAKE_NULL if (strcmp(FAKE_NULL_STR.s,result[i].v.cstr)==0) { result[i].flags |= DB_NULL; } #endif break; case DB_DATETIME: memset(&t, '\0', sizeof(struct tm)); t.tm_sec = rp->time.second; t.tm_min = rp->time.minute; t.tm_hour = rp->time.hour; t.tm_mday = rp->time.day; t.tm_mon = rp->time.month - 1; t.tm_year = rp->time.year - 1900; /* Daylight saving information got lost in the database * so let timegm to guess it. This eliminates the bug when * contacts reloaded from the database have different time * of expiration by one hour when daylight saving is used */ t.tm_isdst = -1; #ifdef HAVE_TIMEGM result[i].v.time = timegm(&t); #else result[i].v.time = _timegm(&t); #endif /* HAVE_TIMEGM */ break; case DB_INT: #ifdef MYSQL_FAKE_NULL if (FAKE_NULL_INT==result[i].v.int4) { result[i].flags |= DB_NULL; } break; #endif case DB_NONE: case DB_FLOAT: case DB_DOUBLE: case DB_BITMAP: /* No need to do anything for these types */ break; } } return 0; }
SB *sb_addchar(SB *sb, char a){ return sb_add(sb, & a, 1); }