summaryrefslogtreecommitdiffstats
path: root/sys/netinet/tcp_subr.c
diff options
context:
space:
mode:
authorandre <andre@FreeBSD.org>2007-05-18 19:58:37 +0000
committerandre <andre@FreeBSD.org>2007-05-18 19:58:37 +0000
commit696f13b7fdbc64ff2137b4759d3fcc0bae6121b3 (patch)
treed51b510129fddae06935d023c8528c4a3a87232d /sys/netinet/tcp_subr.c
parentb753e575a766d7e9e6f70bacf49e41516a9e5556 (diff)
downloadFreeBSD-src-696f13b7fdbc64ff2137b4759d3fcc0bae6121b3.zip
FreeBSD-src-696f13b7fdbc64ff2137b4759d3fcc0bae6121b3.tar.gz
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); }
Diffstat (limited to 'sys/netinet/tcp_subr.c')
-rw-r--r--sys/netinet/tcp_subr.c89
1 files changed, 89 insertions, 0 deletions
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index ffa6cf1..ae05125 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 <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);
+}
OpenPOWER on IntegriCloud