diff --git a/sys/netinet/tcp.h b/sys/netinet/tcp.h index 3f7424d112c9..6c31b5f5a7f0 100644 --- a/sys/netinet/tcp.h +++ b/sys/netinet/tcp.h @@ -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 */ diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index 163b58842d21..02a9c220201d 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -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 diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index ffa6cf175a72..ae05125c4db3 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -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 " + */ +#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); +} diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h index c1c0a804fe03..5b5eff0c0124 100644 --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -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);