Add tcp_log_addrs() function to generate and standardized TCP log line

for use thoughout the tcp subsystem.

It is IPv4 and IPv6 aware creates a line in the following format:

 "TCP: [1.2.3.4]:50332 to [1.2.3.4]:80 tcpflags <RST>"

A "\n" is not included at the end.  The caller is supposed to add
further information after the standard tcp log header.

The function returns a NUL terminated string which the caller has
to free(s, M_TCPLOG) after use.  All memory allocation is done
with M_NOWAIT and the return value may be NULL in memory shortage
situations.

Either struct in_conninfo || (struct tcphdr && (struct ip || struct
ip6_hdr) have to be supplied.

Due to ip[6].h header inclusion limitations and ordering issues the
struct ip and struct ip6_hdr parameters have to be casted and passed
as void * pointers.

tcp_log_addrs(struct in_conninfo *inc, struct tcphdr *th, void *ip4hdr,
    void *ip6hdr)

Usage example:

 struct ip *ip;
 char *tcplog;

 if (tcplog = tcp_log_addrs(NULL, th, (void *)ip, NULL)) {
	log(LOG_DEBUG, "%s; %s: Connection attempt to closed port\n",
	    tcplog, __func__);
	free(s, M_TCPLOG);
 }
This commit is contained in:
andre 2007-05-18 19:58:37 +00:00
parent b753e575a7
commit 696f13b7fd
4 changed files with 101 additions and 22 deletions

View File

@ -69,6 +69,7 @@ struct tcphdr {
#define TH_ECE 0x40
#define TH_CWR 0x80
#define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG|TH_ECE|TH_CWR)
#define PRINT_TH_FLAGS "\20\1FIN\2SYN\3RST\4PUSH\5ACK\6URG\7ECE"
u_short th_win; /* window */
u_short th_sum; /* checksum */

View File

@ -240,7 +240,6 @@ tcp_input(struct mbuf *m, int off0)
#ifdef INET6
struct ip6_hdr *ip6 = NULL;
int isipv6;
char ip6buf[INET6_ADDRSTRLEN];
#else
const int isipv6 = 0;
#endif
@ -481,30 +480,17 @@ tcp_input(struct mbuf *m, int off0)
*/
if ((tcp_log_in_vain == 1 && (thflags & TH_SYN)) ||
tcp_log_in_vain == 2) {
#ifndef INET6
char dbuf[4*sizeof "123"], sbuf[4*sizeof "123"];
char *s;
#ifdef INET6
s = tcp_log_addrs(NULL, th, (void *)ip, (void *)ip6);
#else
char dbuf[INET6_ADDRSTRLEN+2], sbuf[INET6_ADDRSTRLEN+2];
if (isipv6) {
strcpy(dbuf, "[");
strcat(dbuf,
ip6_sprintf(ip6buf, &ip6->ip6_dst));
strcat(dbuf, "]");
strcpy(sbuf, "[");
strcat(sbuf,
ip6_sprintf(ip6buf, &ip6->ip6_src));
strcat(sbuf, "]");
} else
s = tcp_log_addrs(NULL, th, (void *)ip, NULL);
#endif /* INET6 */
{
strcpy(dbuf, inet_ntoa(ip->ip_dst));
strcpy(sbuf, inet_ntoa(ip->ip_src));
if (s != NULL) {
log(LOG_INFO, "%s; %s: Connection attempt "
"to closed port\n", s, __func__);
free(s, M_TCPLOG);
}
log(LOG_INFO,
"Connection attempt to TCP %s:%d "
"from %s:%d flags:0x%02x\n",
dbuf, ntohs(th->th_dport), sbuf,
ntohs(th->th_sport), thflags);
}
/*
* When blackholing do not respond with a RST but

View File

@ -222,6 +222,7 @@ struct tcpcb_mem {
};
static uma_zone_t tcpcb_zone;
MALLOC_DEFINE(M_TCPLOG, "tcplog", "TCP address and flags print buffers");
struct callout isn_callout;
static struct mtx isn_mtx;
@ -2062,3 +2063,91 @@ sysctl_drop(SYSCTL_HANDLER_ARGS)
SYSCTL_PROC(_net_inet_tcp, TCPCTL_DROP, drop,
CTLTYPE_STRUCT|CTLFLAG_WR|CTLFLAG_SKIP, NULL,
0, sysctl_drop, "", "Drop TCP connection");
/*
* Generate a standardized TCP log line for use throughout the
* tcp subsystem. Memory allocation is done with M_NOWAIT to
* allow use in the interrupt context.
*
* NB: The caller MUST free(s, M_TCPLOG) the returned string.
* NB: The function may return NULL if memory allocation failed.
*
* Due to header inclusion and ordering limitations the struct ip
* and ip6_hdr pointers have to be passed as void pointers.
*/
char *
tcp_log_addrs(struct in_conninfo *inc, struct tcphdr *th, void *ip4hdr,
void *ip6hdr)
{
char *s, *sp;
size_t size;
struct ip *ip;
#ifdef INET6
struct ip6_hdr *ip6;
ip6 = (struct ip6_hdr *)ip6hdr;
#endif /* INET6 */
ip = (struct ip *)ip4hdr;
/*
* XXX: The size calculation is evil.
* "TCP: [1.2.3.4]:50332 to [1.2.3.4]:80 tcpflags <RST>"
*/
#ifdef INET6
size = 5 + 2 * (INET6_ADDRSTRLEN + 10) + 12 + 12 * 4 + 1;
#else
size = 5 + 2 * (sizeof("192.168.172.190") + 10) + 12 + 12 *4 + 1;
#endif /* INET6 */
s = sp = malloc(size, M_TCPLOG, (M_ZERO|M_NOWAIT));
if (s == NULL)
return (NULL);
strcat(s, "TCP: [");
sp = s + strlen(s);
if (inc && inc->inc_isipv6 == 0) {
inet_ntoa_r(inc->inc_faddr, sp);
sp = s + strlen(s);
sprintf(sp, "]:%i to [", ntohs(inc->inc_fport));
sp = s + strlen(s);
inet_ntoa_r(inc->inc_laddr, sp);
sp = s + strlen(s);
sprintf(sp, "]:%i", ntohs(inc->inc_lport));
#ifdef INET6
} else if (inc) {
ip6_sprintf(sp, &inc->inc6_faddr);
sp = s + strlen(s);
sprintf(sp, "]:%i to [", ntohs(inc->inc_fport));
sp = s + strlen(s);
ip6_sprintf(sp, &inc->inc6_laddr);
sp = s + strlen(s);
sprintf(sp, "]:%i", ntohs(inc->inc_lport));
} else if (ip6 && th) {
ip6_sprintf(sp, &ip6->ip6_src);
sp = s + strlen(s);
sprintf(sp, "]:%i to [", ntohs(th->th_sport));
sp = s + strlen(s);
ip6_sprintf(sp, &ip6->ip6_dst);
sp = s + strlen(s);
sprintf(sp, "]:%i", ntohs(th->th_dport));
#endif /* INET6 */
} else if (ip && th) {
inet_ntoa_r(ip->ip_src, sp);
sp = s + strlen(s);
sprintf(sp, "]:%i to [", ntohs(th->th_sport));
sp = s + strlen(s);
inet_ntoa_r(ip->ip_dst, sp);
sp = s + strlen(s);
sprintf(sp, "]:%i", ntohs(th->th_dport));
} else {
free(s, M_TCPLOG);
return (NULL);
}
sp = s + strlen(s);
if (th)
sprintf(sp, " tcpflags 0x%b", th->th_flags, PRINT_TH_FLAGS);
if (s[size] != '\0')
panic("%s: string too long", __func__);
return (s);
}

View File

@ -488,6 +488,7 @@ struct xtcpcb {
#ifdef SYSCTL_DECL
SYSCTL_DECL(_net_inet_tcp);
SYSCTL_DECL(_net_inet_tcp_sack);
MALLOC_DECLARE(M_TCPLOG);
#endif
extern struct inpcbhead tcb; /* head of queue of active tcpcb's */
@ -520,6 +521,8 @@ void tcp_drain(void);
void tcp_fasttimo(void);
void tcp_init(void);
void tcp_fini(void *);
char *tcp_log_addrs(struct in_conninfo *, struct tcphdr *, void *,
void *);
int tcp_reass(struct tcpcb *, struct tcphdr *, int *, struct mbuf *);
void tcp_reass_init(void);
void tcp_input(struct mbuf *, int);