Avoid static buffer for protocol hdrinfo functions

This commit is contained in:
dmiller 2026-05-12 18:09:00 +00:00
parent 4ba5b9c335
commit 2d46c6b86c
3 changed files with 297 additions and 308 deletions

View file

@ -441,15 +441,20 @@ char *format_ip_options(const u8* ipopt, int ipoptlen);
#define MEDIUM_DETAIL 2 #define MEDIUM_DETAIL 2
#define HIGH_DETAIL 3 #define HIGH_DETAIL 3
const char *ippackethdrinfo(const u8 *packet, u32 len, int detail); const char *ippackethdrinfo(const u8 *packet, u32 len, int detail);
const char *tcphdrinfo (const u8 *data, unsigned int datalen, int detail, int tcppackethdrinfo (const u8 *data, unsigned int datalen,
char *outbuf, int outlen, int detail,
int frag_off, const char *srchost, const char *dsthost); int frag_off, const char *srchost, const char *dsthost);
const char *udphdrinfo (const u8 *data, unsigned int datalen, int detail, int udppackethdrinfo (const u8 *data, unsigned int datalen,
char *outbuf, int outlen, int detail,
int frag_off, const char *srchost, const char *dsthost); int frag_off, const char *srchost, const char *dsthost);
const char *sctphdrinfo (const u8 *data, unsigned int datalen, int detail, int sctppackethdrinfo (const u8 *data, unsigned int datalen,
char *outbuf, int outlen, int detail,
int frag_off, const char *srchost, const char *dsthost); int frag_off, const char *srchost, const char *dsthost);
const char *icmphdrinfo (const u8 *data, unsigned int datalen, int detail, int icmppackethdrinfo (const u8 *data, unsigned int datalen,
char *outbuf, int outlen, int detail,
int frag_off, const char *srchost, const char *dsthost); int frag_off, const char *srchost, const char *dsthost);
const char *icmp6hdrinfo (const u8 *data, unsigned int datalen, int detail, int icmp6packethdrinfo (const u8 *data, unsigned int datalen,
char *outbuf, int outlen, int detail,
int frag_off, const char *srchost, const char *dsthost); int frag_off, const char *srchost, const char *dsthost);

View file

@ -608,34 +608,32 @@ const char *ippackethdrinfo(const u8 *packet, u32 len, int detail) {
} }
} }
char *p = protoinfo;
int remains = sizeof(protoinfo);
int used = 0;
if (hdr.proto == IPPROTO_TCP) { if (hdr.proto == IPPROTO_TCP) {
Snprintf(protoinfo, sizeof(protoinfo), "%s IP [%s]", tcphdrinfo(data, datalen, detail, frag_off, srchost, dsthost), ipinfo); used = tcppackethdrinfo(data, datalen, p, remains, detail, frag_off, srchost, dsthost);
} }
else if (hdr.proto == IPPROTO_UDP) { else if (hdr.proto == IPPROTO_UDP) {
Snprintf(protoinfo, sizeof(protoinfo), "%s IP [%s]", udphdrinfo(data, datalen, detail, frag_off, srchost, dsthost), ipinfo); used = udppackethdrinfo(data, datalen, p, remains, detail, frag_off, srchost, dsthost);
} }
else if (hdr.proto == IPPROTO_SCTP) { else if (hdr.proto == IPPROTO_SCTP) {
Snprintf(protoinfo, sizeof(protoinfo), "%s IP [%s]", sctphdrinfo(data, datalen, detail, frag_off, srchost, dsthost), ipinfo); used = sctppackethdrinfo(data, datalen, p, remains, detail, frag_off, srchost, dsthost);
} }
else if (hdr.proto == IPPROTO_ICMP) { else if (hdr.proto == IPPROTO_ICMP) {
Snprintf(protoinfo, sizeof(protoinfo), "%s IP [%s]", icmphdrinfo(data, datalen, detail, frag_off, srchost, dsthost), ipinfo); used = icmppackethdrinfo(data, datalen, p, remains, detail, frag_off, srchost, dsthost);
} }
else if (hdr.proto == IPPROTO_ICMPV6) { else if (hdr.proto == IPPROTO_ICMPV6) {
Snprintf(protoinfo, sizeof(protoinfo), "%s IP [%s]", icmp6hdrinfo(data, datalen, detail, frag_off, srchost, dsthost), ipinfo); used = icmp6packethdrinfo(data, datalen, p, remains, detail, frag_off, srchost, dsthost);
} }
else { else {
/* UNKNOWN PROTOCOL **********************************************************/ /* UNKNOWN PROTOCOL **********************************************************/
const char *hdrstr; used = Snprintf(p, remains, "%s (%d) %s > %s",
nexthdrtoa(hdr.proto, 1), hdr.proto, srchost, dsthost);
hdrstr = nexthdrtoa(hdr.proto, 1);
if (hdrstr == NULL || *hdrstr == '\0') {
Snprintf(protoinfo, sizeof(protoinfo), "Unknown protocol (%d) %s > %s: %s",
hdr.proto, srchost, dsthost, ipinfo);
} else {
Snprintf(protoinfo, sizeof(protoinfo), "%s (%d) %s > %s: %s",
hdrstr, hdr.proto, srchost, dsthost, ipinfo);
}
} }
p += used;
remains -= used;
Snprintf(p, remains, " IP [%s]", ipinfo);
return protoinfo; return protoinfo;
} }
@ -657,7 +655,8 @@ static const char *get_addrstr(const char *host, char strbuf[INFO_ADDRSTRLEN])
return host; return host;
} }
const char *tcphdrinfo (const u8 *data, unsigned int datalen, int detail, int tcppackethdrinfo (const u8 *data, unsigned int datalen,
char *outbuf, int outlen, int detail,
int frag_off, const char *srchost, const char *dsthost) int frag_off, const char *srchost, const char *dsthost)
{ {
char srcstr[INFO_ADDRSTRLEN] = ""; char srcstr[INFO_ADDRSTRLEN] = "";
@ -666,7 +665,6 @@ const char *tcphdrinfo (const u8 *data, unsigned int datalen, int detail,
dsthost = get_addrstr(dsthost, dststr); dsthost = get_addrstr(dsthost, dststr);
/* TCP INFORMATION ***********************************************************/ /* TCP INFORMATION ***********************************************************/
static char protoinfo[512] = "";
char tcpoptinfo[256] = ""; char tcpoptinfo[256] = "";
struct tcp_hdr tcp; struct tcp_hdr tcp;
@ -683,18 +681,17 @@ const char *tcphdrinfo (const u8 *data, unsigned int datalen, int detail,
* less than 8 bytes. This also includes empty IP packets that say they * less than 8 bytes. This also includes empty IP packets that say they
* contain a TCP packet. */ * contain a TCP packet. */
if (frag_off > 8 || datalen < 8 || (frag_off % 8 != 0)) { if (frag_off > 8 || datalen < 8 || (frag_off % 8 != 0)) {
Snprintf(protoinfo, sizeof(protoinfo), "TCP %s:?? > %s:?? ?? (incomplete)", return Snprintf(outbuf, outlen, "TCP %s:?? > %s:?? ?? (incomplete)",
srchost, dsthost); srchost, dsthost);
} }
/* For all cases after this, datalen is necessarily >= 8 and frag_off is <= 8 */ /* For all cases after this, datalen is necessarily >= 8 and frag_off is <= 8 */
else {
memcpy((u8 *)&tcp + frag_off, data, MIN(datalen, sizeof(tcp) - frag_off)); memcpy((u8 *)&tcp + frag_off, data, MIN(datalen, sizeof(tcp) - frag_off));
/* how much of the original packet do we have? */ /* how much of the original packet do we have? */
int lastbyte = datalen + frag_off; int lastbyte = datalen + frag_off;
bool have_seq=false, have_flags_win=false, have_sum_urp=false; bool have_seq=false, have_flags_win=false, have_sum_urp=false;
char *p = protoinfo; char *p = outbuf;
int remains = sizeof(protoinfo) - 1; int remains = outlen;
int used = 0; int used = 0;
u32 tcpdataoffset = 0; u32 tcpdataoffset = 0;
@ -783,11 +780,11 @@ tcpdone:
remains -= used; remains -= used;
} }
assert(remains > 0); assert(remains > 0);
} return outlen - remains;
return protoinfo;
} }
const char *udphdrinfo (const u8 *data, unsigned int datalen, int detail, int udppackethdrinfo (const u8 *data, unsigned int datalen,
char *outbuf, int outlen, int detail,
int frag_off, const char *srchost, const char *dsthost) int frag_off, const char *srchost, const char *dsthost)
{ {
char srcstr[INFO_ADDRSTRLEN] = ""; char srcstr[INFO_ADDRSTRLEN] = "";
@ -795,31 +792,30 @@ const char *udphdrinfo (const u8 *data, unsigned int datalen, int detail,
srchost = get_addrstr(srchost, srcstr); srchost = get_addrstr(srchost, srcstr);
dsthost = get_addrstr(dsthost, dststr); dsthost = get_addrstr(dsthost, dststr);
static char protoinfo[512] = "";
/* UDP INFORMATION ***********************************************************/ /* UDP INFORMATION ***********************************************************/
if((frag_off || datalen < sizeof(struct udp_hdr))) { if((frag_off || datalen < sizeof(struct udp_hdr))) {
Snprintf(protoinfo, sizeof(protoinfo), "UDP %s:?? > %s:?? fragment (incomplete)", return Snprintf(outbuf, outlen, "UDP %s:?? > %s:?? fragment (incomplete)",
srchost, dsthost); srchost, dsthost);
} else { }
struct udp_hdr udp; struct udp_hdr udp;
memcpy(&udp, data, sizeof(udp)); memcpy(&udp, data, sizeof(udp));
if (detail == LOW_DETAIL) { if (detail == LOW_DETAIL) {
Snprintf(protoinfo, sizeof(protoinfo), "UDP %s:%hu > %s:%hu", return Snprintf(outbuf, outlen, "UDP %s:%hu > %s:%hu",
srchost, (unsigned short) ntohs(udp.uh_sport), dsthost, (unsigned short) ntohs(udp.uh_dport)); srchost, (unsigned short) ntohs(udp.uh_sport), dsthost, (unsigned short) ntohs(udp.uh_dport));
} else if (detail == MEDIUM_DETAIL) { } else if (detail == MEDIUM_DETAIL) {
Snprintf(protoinfo, sizeof(protoinfo), "UDP [%s:%hu > %s:%hu csum=0x%04X]", return Snprintf(outbuf, outlen, "UDP [%s:%hu > %s:%hu csum=0x%04X]",
srchost, (unsigned short) ntohs(udp.uh_sport), dsthost, (unsigned short) ntohs(udp.uh_dport), ntohs(udp.uh_sum)); srchost, (unsigned short) ntohs(udp.uh_sport), dsthost, (unsigned short) ntohs(udp.uh_dport), ntohs(udp.uh_sum));
} else if (detail == HIGH_DETAIL) { } else if (detail == HIGH_DETAIL) {
Snprintf(protoinfo, sizeof(protoinfo), "UDP [%s:%hu > %s:%hu len=%hu csum=0x%04X]", return Snprintf(outbuf, outlen, "UDP [%s:%hu > %s:%hu len=%hu csum=0x%04X]",
srchost, (unsigned short) ntohs(udp.uh_sport), dsthost, (unsigned short) ntohs(udp.uh_dport), srchost, (unsigned short) ntohs(udp.uh_sport), dsthost, (unsigned short) ntohs(udp.uh_dport),
(unsigned short) ntohs(udp.uh_ulen), ntohs(udp.uh_sum)); (unsigned short) ntohs(udp.uh_ulen), ntohs(udp.uh_sum));
} }
} return 0;
return protoinfo;
} }
const char *sctphdrinfo (const u8 *data, unsigned int datalen, int detail, int sctppackethdrinfo (const u8 *data, unsigned int datalen,
char *outbuf, int outlen, int detail,
int frag_off, const char *srchost, const char *dsthost) int frag_off, const char *srchost, const char *dsthost)
{ {
char srcstr[INFO_ADDRSTRLEN] = ""; char srcstr[INFO_ADDRSTRLEN] = "";
@ -827,45 +823,45 @@ const char *sctphdrinfo (const u8 *data, unsigned int datalen, int detail,
srchost = get_addrstr(srchost, srcstr); srchost = get_addrstr(srchost, srcstr);
dsthost = get_addrstr(dsthost, dststr); dsthost = get_addrstr(dsthost, dststr);
static char protoinfo[512] = "";
/* SCTP INFORMATION **********************************************************/ /* SCTP INFORMATION **********************************************************/
if ((frag_off || datalen < sizeof(struct sctp_hdr))) { if ((frag_off || datalen < sizeof(struct sctp_hdr))) {
Snprintf(protoinfo, sizeof(protoinfo), "SCTP %s:?? > %s:?? fragment (incomplete)", return Snprintf(outbuf, outlen, "SCTP %s:?? > %s:?? fragment (incomplete)",
srchost, dsthost); srchost, dsthost);
} else { }
struct sctp_hdr sctp; struct sctp_hdr sctp;
memcpy(&sctp, data, sizeof(sctp)); memcpy(&sctp, data, sizeof(sctp));
if (detail == LOW_DETAIL) { if (detail == LOW_DETAIL) {
Snprintf(protoinfo, sizeof(protoinfo), "SCTP %s:%hu > %s:%hu", return Snprintf(outbuf, outlen, "SCTP %s:%hu > %s:%hu",
srchost, (unsigned short) ntohs(sctp.sh_sport), dsthost, (unsigned short) ntohs(sctp.sh_dport)); srchost, (unsigned short) ntohs(sctp.sh_sport), dsthost, (unsigned short) ntohs(sctp.sh_dport));
} else if (detail == MEDIUM_DETAIL) { } else if (detail == MEDIUM_DETAIL) {
Snprintf(protoinfo, sizeof(protoinfo), "SCTP [%s:%hu > %s:%hu csum=0x%08x]", return Snprintf(outbuf, outlen, "SCTP [%s:%hu > %s:%hu csum=0x%08x]",
srchost, (unsigned short) ntohs(sctp.sh_sport), dsthost, (unsigned short) ntohs(sctp.sh_dport), ntohl(sctp.sh_sum)); srchost, (unsigned short) ntohs(sctp.sh_sport), dsthost, (unsigned short) ntohs(sctp.sh_dport), ntohl(sctp.sh_sum));
} else if (detail == HIGH_DETAIL) { } else if (detail == HIGH_DETAIL) {
Snprintf(protoinfo, sizeof(protoinfo), "SCTP [%s:%hu > %s:%hu vtag=%lu csum=0x%08x]", return Snprintf(outbuf, outlen, "SCTP [%s:%hu > %s:%hu vtag=%lu csum=0x%08x]",
srchost, (unsigned short) ntohs(sctp.sh_sport), dsthost, (unsigned short) ntohs(sctp.sh_dport), srchost, (unsigned short) ntohs(sctp.sh_sport), dsthost, (unsigned short) ntohs(sctp.sh_dport),
(unsigned long) ntohl(sctp.sh_vtag), ntohl(sctp.sh_sum)); (unsigned long) ntohl(sctp.sh_vtag), ntohl(sctp.sh_sum));
} }
} return 0;
return protoinfo;
} }
const char *icmphdrinfo (const u8 *data, unsigned int datalen, int detail, int icmppackethdrinfo (const u8 *data, unsigned int datalen,
char *outbuf, int outlen, int detail,
int frag_off, const char *srchost, const char *dsthost) int frag_off, const char *srchost, const char *dsthost)
{ {
if (srchost == NULL) if (srchost == NULL)
srchost = "??"; srchost = "??";
if (dsthost == NULL) if (dsthost == NULL)
dsthost = "??"; dsthost = "??";
static char protoinfo[512] = "";
char icmptype[128] = ""; /* Temp info about ICMP type & code */ char icmptype[128] = ""; /* Temp info about ICMP type & code */
char icmpfields[256] = ""; /* Temp info for various ICMP fields */ char icmpfields[256] = ""; /* Temp info for various ICMP fields */
/* ICMP INFORMATION **********************************************************/ /* ICMP INFORMATION **********************************************************/
if((frag_off || datalen < sizeof(struct icmp_hdr))) { if((frag_off || datalen < sizeof(struct icmp_hdr))) {
Snprintf(protoinfo, sizeof(protoinfo), "ICMP %s > %s fragment (incomplete)", return Snprintf(outbuf, outlen, "ICMP %s > %s fragment (incomplete)",
srchost, dsthost); srchost, dsthost);
} else { }
struct ip_hdr ip2; /* Points to the IP datagram carried by some ICMP messages */ struct ip_hdr ip2; /* Points to the IP datagram carried by some ICMP messages */
char *ip2dst; /* Dest IP in caried IP datagram */ char *ip2dst; /* Dest IP in caried IP datagram */
char auxbuff[128]; /* Aux buffer */ char auxbuff[128]; /* Aux buffer */
@ -1142,43 +1138,41 @@ const char *icmphdrinfo (const u8 *data, unsigned int datalen, int detail,
icmpbad: icmpbad:
if (icmptype[0] != '\0') { if (icmptype[0] != '\0') {
/* We still have this information */ /* We still have this information */
Snprintf(protoinfo, sizeof(protoinfo), "ICMP %s > %s %s (type=%d/code=%d)", return Snprintf(outbuf, outlen, "ICMP %s > %s %s (type=%d/code=%d)",
srchost, dsthost, icmptype, icmp.icmp_type, icmp.icmp_code); srchost, dsthost, icmptype, icmp.icmp_type, icmp.icmp_code);
} else { } else {
Snprintf(protoinfo, sizeof(protoinfo), "ICMP %s > %s [??]", return Snprintf(outbuf, outlen, "ICMP %s > %s [??]",
srchost, dsthost); srchost, dsthost);
} }
} else { } else {
char icmpinfo[512] = ""; /* Temp info about ICMP. */ char icmpinfo[512] = ""; /* Temp info about ICMP. */
sprintf(icmpinfo,"type=%d/code=%d", icmp.icmp_type, icmp.icmp_code); sprintf(icmpinfo,"type=%d/code=%d", icmp.icmp_type, icmp.icmp_code);
Snprintf(protoinfo, sizeof(protoinfo), "ICMP [%s > %s %s (%s) %s]", return Snprintf(outbuf, outlen, "ICMP [%s > %s %s (%s) %s]",
srchost, dsthost, icmptype, icmpinfo, icmpfields); srchost, dsthost, icmptype, icmpinfo, icmpfields);
} }
} }
return protoinfo;
}
const char *icmp6hdrinfo (const u8 *data, unsigned int datalen, int detail, int icmp6packethdrinfo (const u8 *data, unsigned int datalen,
char *outbuf, int outlen, int detail,
int frag_off, const char *srchost, const char *dsthost) int frag_off, const char *srchost, const char *dsthost)
{ {
if (srchost == NULL) if (srchost == NULL)
srchost = "??"; srchost = "??";
if (dsthost == NULL) if (dsthost == NULL)
dsthost = "??"; dsthost = "??";
static char protoinfo[512] = "";
if (frag_off || datalen < sizeof(struct icmpv6_hdr)) { if (frag_off || datalen < sizeof(struct icmpv6_hdr)) {
Snprintf(protoinfo, sizeof(protoinfo), "ICMPv6 %s > %s (type=?/code=?)", return Snprintf(outbuf, outlen, "ICMPv6 %s > %s (type=?/code=?)",
srchost, dsthost); srchost, dsthost);
} }
else { else {
const struct icmpv6_hdr *icmpv6; const struct icmpv6_hdr *icmpv6;
icmpv6 = (struct icmpv6_hdr *) data; icmpv6 = (struct icmpv6_hdr *) data;
Snprintf(protoinfo, sizeof(protoinfo), "ICMPv6 %s > %s (type=%d/code=%d)", return Snprintf(outbuf, outlen, "ICMPv6 %s > %s (type=%d/code=%d)",
srchost, dsthost, srchost, dsthost,
icmpv6->icmpv6_type, icmpv6->icmpv6_code); icmpv6->icmpv6_type, icmpv6->icmpv6_code);
} }
return protoinfo;
} }

View file

@ -904,37 +904,27 @@ int arppackethdrinfo(const u8 *packet, u32 len, u8 *dstbuff, u32 dstlen){
} /* End of arppackethdrinfo() */ } /* End of arppackethdrinfo() */
int tcppackethdrinfo(const u8 *packet, size_t len, u8 *dstbuff, size_t dstlen, int tcppackethdrinfo(const u8 *packet, size_t len, u8 *dstbuff, size_t dstlen,
int detail, const char *src, const char *dst){ int detail, const char *src, const char *dst){
assert(packet); assert(packet);
assert(dstbuff); assert(dstbuff);
const char *protoinfo = tcphdrinfo(packet, len, detail, 0, src, dst); return (tcppackethdrinfo(packet, len, (char *)dstbuff, dstlen,
Strncpy((char*)dstbuff, protoinfo, dstlen); detail, 0, src, dst) > 0 ? OP_SUCCESS : OP_FAILURE);
return OP_SUCCESS;
} /* End of tcppackethdrinfo() */ } /* End of tcppackethdrinfo() */
int udppackethdrinfo(const u8 *packet, size_t len, u8 *dstbuff, size_t dstlen, int udppackethdrinfo(const u8 *packet, size_t len, u8 *dstbuff, size_t dstlen,
int detail, const char *src, const char *dst){ int detail, const char *src, const char *dst){
assert(packet); assert(packet);
assert(dstbuff); assert(dstbuff);
const char *protoinfo = udphdrinfo(packet, len, detail, 0, src, dst); return (udppackethdrinfo(packet, len, (char *)dstbuff, dstlen,
strncpy((char*)dstbuff, protoinfo, dstlen); detail, 0, src, dst) > 0 ? OP_SUCCESS : OP_FAILURE);
return OP_SUCCESS;
} /* End of udppackethdrinfo() */ } /* End of udppackethdrinfo() */
/** Returns a random (null-terminated) ASCII string with no special /** Returns a random (null-terminated) ASCII string with no special
* meaning. Returned string may be between 1 and 512 bytes and contain * meaning. Returned string may be between 1 and 512 bytes and contain
* random letters and some whitespace. * random letters and some whitespace.