static void type_add_str_pre( type *r, int *need_paren, int *need_spc, char **bufp, int *sz) { type *prev_skipped; enum type_qualifier q = qual_none; /* int (**fn())[2] * btype -> array -> ptr -> ptr -> func * ^ parens * * .tmp looks right, down the chain, .ref looks left, up the chain */ *need_paren = r->ref && IS_PTR(r->type) && (prev_skipped = type_skip_all(r->ref))->type != type_btype && !IS_PTR(prev_skipped->type); if(*need_paren){ ADD_SPC(); BUF_ADD("("); } switch(r->type){ case type_ptr: #ifdef SHOW_DECAYED_ARRAYS if(r->bits.ptr.size) break; /* decayed array */ #endif ADD_SPC(); BUF_ADD("*"); break; case type_cast: q = r->bits.cast.qual; break; case type_block: ADD_SPC(); BUF_ADD("^"); break; default:break; } if(q){ ADD_SPC(); BUF_ADD("%s", type_qual_to_str(q, 0)); *need_spc = 1; /* space out after qualifier, e.g. * int *const p; * ^ * int const a; * ^ */ } }
static void ipt_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) { static char buf[4096]; size_t buf_siz = sizeof(buf); size_t buf_len = 0; *buf = '\0'; if (!loginfo) loginfo = &default_loginfo; spin_lock_bh(&log_lock); BUF_ADD(buf,buf_siz,buf_len, "<%d>%sIN=%s OUT=%s ", loginfo->u.log.level, prefix[0] ? prefix : "netfilter: ", 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) BUF_ADD(buf,buf_siz,buf_len, "PHYSIN=%s ", physindev->name); physoutdev = skb->nf_bridge->physoutdev; if (physoutdev && out != physoutdev) BUF_ADD(buf,buf_siz,buf_len, "PHYSOUT=%s ", physoutdev->name); } #endif if (in && !out) { /* MAC logging for input chain only. */ BUF_ADD(buf,buf_siz,buf_len, "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++) BUF_ADD(buf,buf_siz,buf_len, "%02x%c", *p, i==skb->dev->hard_header_len - 1 ? ' ':':'); } else BUF_ADD(buf,buf_siz,buf_len, " "); } dump_packet(loginfo, skb, 0, buf, buf_siz); BUF_ADD(buf,buf_siz,buf_len, "\n"); send_data(buf, strlen(buf)); spin_unlock_bh(&log_lock); }
char * IpConn_fmt(IpConn *conn, char *buf, int n) { char *buf_orig = buf; int i, err=-1; char *p; do { i = snprintf(buf, n, "connection=%p ", conn); BUF_ADD(buf, n, i); if( !conn ) { err = 0; break; } p = IpConnAddr_fmt(&conn->conn_addr, buf, n); i = p ? strlen(buf) : -1; BUF_ADD(buf, n, i); i = snprintf(buf, n, " flags=%s%s%s" " dt=%.3f" " client(bytes=%ld pkt=%ld buf=%d)" " server(bytes=%ld pkt=%ld buf=%d)" ,(conn->conn_pkt_flags & CONN_PKT_FIRST ? "f" : "-") ,(conn->conn_pkt_flags & CONN_PKT_FROM_CLIENT ? "c" : "-") ,(conn->conn_pkt_flags & CONN_PKT_FROM_SERVER ? "s" : "-") ,mstime() - conn->conn_time_prev ,conn->conn_stats_client.bytes ,conn->conn_stats_client.packets ,array_count(&conn->queue_client.buf) ,conn->conn_stats_server.bytes ,conn->conn_stats_server.packets ,array_count(&conn->queue_server.buf) ); BUF_ADD(buf, n, i); err = 0; } while(0); return err ? 0 : buf_orig; }
static void type_add_funcargs( funcargs *args, int *need_spc, char **bufp, int *sz) { const char *comma = ""; decl **i; ADD_SPC(); BUF_ADD("("); for(i = args->arglist; i && *i; i++){ char tmp_buf[DECL_STATIC_BUFSIZ]; decl *d = *i; BUF_ADD("%s%s", comma, decl_store_spel_type_to_str_r(tmp_buf, d->store, NULL, d->ref)); comma = ", "; } BUF_ADD("%s)", args->variadic ? ", ..." : args->args_void ? "void" : ""); }
char* IpConnAddr_fmt(IpConnAddr *addr, char *buf, int n) { char *buf_orig = buf; int i, err=-1; do { netpkt_proto_fmt(addr->proto, buf, n); i = strlen(buf); BUF_ADD(buf, n, i); i = snprintf(buf, n, " server=%s:%d", netpkt_ntoa(addr->server_addr, 0), addr->server_port); BUF_ADD(buf, n, i); i = snprintf(buf, n, " client=%s:%d", netpkt_ntoa(addr->client_addr, 0), addr->client_port); BUF_ADD(buf, n, i); err = 0; } while(0); return err ? 0 : buf_orig; }
static type *type_add_type_str(type *r, char **bufp, int *sz, enum type_str_opts const opts) { /* go down to the first type or typedef, print it and then its descriptions */ type *ty; **bufp = '\0'; for(ty = r; ty && ty->type != type_btype; ty = ty->ref) { if((opts & TY_STR_NO_TDEF) == 0 && ty->type == type_tdef) break; } if(!ty) return NULL; if(ty->type == type_tdef){ char buf[BTYPE_STATIC_BUFSIZ]; decl *d = ty->bits.tdef.decl; type *of; if(d){ BUF_ADD("%s", d->spel); of = d->ref; }else{ expr *const e = ty->bits.tdef.type_of; int const is_type = !e->expr; BUF_ADD("typeof(%s%s)", /* e is always expr_sizeof() */ is_type ? "" : "expr: ", is_type ? type_to_str_r_spel_opts(buf, e->tree_type, NULL, TY_STR_NOOPT) : e->expr->f_str()); /* don't show aka for typeof types - it's there already */ of = is_type ? NULL : e->tree_type; } if((opts & TY_STR_AKA) && of){ /* descend to the type if it's next */ type *t_ref = type_is_primitive(of, type_unknown); const btype *t = t_ref ? t_ref->bits.type : NULL; BUF_ADD(" (aka '%s')", t ? btype_to_str(t) : type_to_str_r_spel_opts(buf, type_skip_tdefs(of), NULL, TY_STR_NOOPT)); } return ty; }else{ BUF_ADD("%s", btype_to_str(ty->bits.type)); } return NULL; }
static void type_add_str( type *r, const char *spel, int *need_spc, char **bufp, int *sz, type *stop_at) { int need_paren; type *array_qual = NULL, *next_ty; if(!r){ /* reached the bottom/end - spel */ if(spel){ ADD_SPC(); BUF_ADD("%s", spel); *need_spc = 0; } return; } if(stop_at && r->tmp == stop_at){ type_add_str(r->tmp, spel, need_spc, bufp, sz, stop_at); return; } type_add_str_pre(r, &need_paren, need_spc, bufp, sz); next_ty = r->tmp; if(r->type == type_array && r->tmp && r->tmp->type == type_cast){ array_qual = r->tmp; next_ty = array_qual->tmp; } type_add_str(next_ty, spel, need_spc, bufp, sz, stop_at); switch(r->type){ case type_auto: ICE("__auto_type"); case type_tdef: /* tdef "aka: %s" handled elsewhere */ case type_attr: /* attribute not handled here */ case type_btype: case type_cast: case type_where: /**/ case type_block: break; case type_func: type_add_funcargs(r->bits.func.args, need_spc, bufp, sz); break; case type_ptr: #ifdef SHOW_DECAYED_ARRAYS if(!r->bits.ptr.size) #endif break; /* fall */ case type_array: { const char *sz_space = ""; BUF_ADD("["); if(r->bits.array.is_vla == 0 && r->bits.array.is_static){ BUF_ADD("static"); sz_space = " "; } if(array_qual){ BUF_ADD("%s%s", sz_space, type_qual_to_str(array_qual->bits.cast.qual, 0)); sz_space = " "; } switch(r->bits.array.is_vla){ case 0: if(r->bits.array.size){ BUF_ADD( "%s%" NUMERIC_FMT_D, sz_space, const_fold_val_i(r->bits.array.size)); } break; case VLA: BUF_ADD("vla"); break; case VLA_STAR: BUF_ADD("*"); break; } BUF_ADD("]"); break; } } if(need_paren) BUF_ADD(")"); #undef IS_PTR }
/* One level of recursion won't kill us */ static void dump_packet(const struct nf_loginfo *info, const struct sk_buff *skb, unsigned int iphoff, char *buf, size_t buf_siz) { struct iphdr _iph; const struct iphdr *ih; unsigned int logflags; size_t buf_len = strlen(buf); #define BUF_ADD(ptr, siz, off, fmt...) \ do { \ off = strlen(ptr); \ snprintf(((ptr)+(off)), ((siz) > (off) ? (siz)-(off) : 0), ##fmt); \ } while (0) 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) { BUF_ADD(buf,buf_siz,buf_len, "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 " */ BUF_ADD(buf,buf_siz,buf_len, "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 " */ BUF_ADD(buf,buf_siz,buf_len, "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) BUF_ADD(buf,buf_siz,buf_len, "CE "); if (ntohs(ih->frag_off) & IP_DF) BUF_ADD(buf,buf_siz,buf_len, "DF "); if (ntohs(ih->frag_off) & IP_MF) BUF_ADD(buf,buf_siz,buf_len, "MF "); /* Max length: 11 "FRAG:65535 " */ if (ntohs(ih->frag_off) & IP_OFFSET) BUF_ADD(buf,buf_siz,buf_len, "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) { BUF_ADD(buf,buf_siz,buf_len, "TRUNCATED"); return; } /* Max length: 127 "OPT (" 15*4*2chars ") " */ BUF_ADD(buf,buf_siz,buf_len, "OPT ("); for (i = 0; i < optsize; i++) BUF_ADD(buf,buf_siz,buf_len, "%02X", op[i]); BUF_ADD(buf,buf_siz,buf_len, ") "); } switch (ih->protocol) { case IPPROTO_TCP: { struct tcphdr _tcph; const struct tcphdr *th; /* Max length: 10 "PROTO=TCP " */ BUF_ADD(buf,buf_siz,buf_len, "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) { BUF_ADD(buf,buf_siz,buf_len, "INCOMPLETE [%u bytes] ", skb->len - iphoff - ih->ihl*4); break; } /* Max length: 20 "SPT=65535 DPT=65535 " */ BUF_ADD(buf,buf_siz,buf_len, "SPT=%u DPT=%u ", ntohs(th->source), ntohs(th->dest)); /* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */ if (logflags & IPT_LOG_TCPSEQ) BUF_ADD(buf,buf_siz,buf_len, "SEQ=%u ACK=%u ", ntohl(th->seq), ntohl(th->ack_seq)); /* Max length: 13 "WINDOW=65535 " */ BUF_ADD(buf,buf_siz,buf_len, "WINDOW=%u ", ntohs(th->window)); /* Max length: 9 "RES=0x3F " */ BUF_ADD(buf,buf_siz,buf_len, "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) BUF_ADD(buf,buf_siz,buf_len, "CWR "); if (th->ece) BUF_ADD(buf,buf_siz,buf_len, "ECE "); if (th->urg) BUF_ADD(buf,buf_siz,buf_len, "URG "); if (th->ack) BUF_ADD(buf,buf_siz,buf_len, "ACK "); if (th->psh) BUF_ADD(buf,buf_siz,buf_len, "PSH "); if (th->rst) BUF_ADD(buf,buf_siz,buf_len, "RST "); if (th->syn) BUF_ADD(buf,buf_siz,buf_len, "SYN "); if (th->fin) BUF_ADD(buf,buf_siz,buf_len, "FIN "); /* Max length: 11 "URGP=65535 " */ BUF_ADD(buf,buf_siz,buf_len, "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)]; const 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) { BUF_ADD(buf,buf_siz,buf_len, "TRUNCATED"); return; } /* Max length: 127 "OPT (" 15*4*2chars ") " */ BUF_ADD(buf,buf_siz,buf_len, "OPT ("); for (i = 0; i < optsize; i++) BUF_ADD(buf,buf_siz,buf_len, "%02X", op[i]); BUF_ADD(buf,buf_siz,buf_len, ") "); } break; } case IPPROTO_UDP: case IPPROTO_UDPLITE: { struct udphdr _udph; const struct udphdr *uh; if (ih->protocol == IPPROTO_UDP) /* Max length: 10 "PROTO=UDP " */ BUF_ADD(buf,buf_siz,buf_len, "PROTO=UDP " ); else /* Max length: 14 "PROTO=UDPLITE " */ BUF_ADD(buf,buf_siz,buf_len, "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) { BUF_ADD(buf,buf_siz,buf_len, "INCOMPLETE [%u bytes] ", skb->len - iphoff - ih->ihl*4); break; } /* Max length: 20 "SPT=65535 DPT=65535 " */ BUF_ADD(buf,buf_siz,buf_len, "SPT=%u DPT=%u LEN=%u ", ntohs(uh->source), ntohs(uh->dest), ntohs(uh->len)); 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 " */ BUF_ADD(buf,buf_siz,buf_len, "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) { BUF_ADD(buf,buf_siz,buf_len, "INCOMPLETE [%u bytes] ", skb->len - iphoff - ih->ihl*4); break; } /* Max length: 18 "TYPE=255 CODE=255 " */ BUF_ADD(buf,buf_siz,buf_len, "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]) { BUF_ADD(buf,buf_siz,buf_len, "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 " */ BUF_ADD(buf,buf_siz,buf_len, "ID=%u SEQ=%u ", ntohs(ich->un.echo.id), ntohs(ich->un.echo.sequence)); break; case ICMP_PARAMETERPROB: /* Max length: 14 "PARAMETER=255 " */ BUF_ADD(buf,buf_siz,buf_len, "PARAMETER=%u ", ntohl(ich->un.gateway) >> 24); break; case ICMP_REDIRECT: /* Max length: 24 "GATEWAY=255.255.255.255 " */ BUF_ADD(buf,buf_siz,buf_len, "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. */ BUF_ADD(buf,buf_siz,buf_len, "["); dump_packet(info, skb, iphoff + ih->ihl*4+sizeof(_icmph), buf, buf_siz); BUF_ADD(buf,buf_siz,buf_len, "] "); } /* Max length: 10 "MTU=65535 " */ if (ich->type == ICMP_DEST_UNREACH && ich->code == ICMP_FRAG_NEEDED) BUF_ADD(buf,buf_siz,buf_len, "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 " */ BUF_ADD(buf,buf_siz,buf_len, "PROTO=AH "); /* Max length: 25 "INCOMPLETE [65535 bytes] " */ ah = skb_header_pointer(skb, iphoff+ih->ihl*4, sizeof(_ahdr), &_ahdr); if (ah == NULL) { BUF_ADD(buf,buf_siz,buf_len, "INCOMPLETE [%u bytes] ", skb->len - iphoff - ih->ihl*4); break; } /* Length: 15 "SPI=0xF1234567 " */ BUF_ADD(buf,buf_siz,buf_len, "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 " */ BUF_ADD(buf,buf_siz,buf_len, "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) { BUF_ADD(buf,buf_siz,buf_len, "INCOMPLETE [%u bytes] ", skb->len - iphoff - ih->ihl*4); break; } /* Length: 15 "SPI=0xF1234567 " */ BUF_ADD(buf,buf_siz,buf_len, "SPI=0x%x ", ntohl(eh->spi)); break; } /* Max length: 10 "PROTO 255 " */ default: BUF_ADD(buf,buf_siz,buf_len, "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) BUF_ADD(buf,buf_siz,buf_len, "UID=%u ", skb->sk->sk_socket->file->f_uid); read_unlock_bh(&skb->sk->sk_callback_lock); } /* 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 */ }