From 678ff80a6f30aaf6f5d6e8e25a44be41543c47ca Mon Sep 17 00:00:00 2001 From: hiren Date: Tue, 15 Nov 2016 22:18:52 +0000 Subject: [PATCH] MFC r302474 (By gnn) On FreeBSD there is a setsockopt option SO_USER_COOKIE which allows setting a 32 bit value on each socket. This can be used by applications and DTrace as a rendezvous point so that an applicaton's data can more easily be captured at run time. Expose the user cookie via DTrace by updating the translator in tcp.d and add a quick test program, a TCP server, that sets the cookie on each connection accepted. Sponsored by: Limelight Networks --- cddl/lib/libdtrace/tcp.d | 3 + tests/sys/netinet/Makefile | 2 +- tests/sys/netinet/tcp_user_cookie.c | 111 ++++++++++++++++++++++++++++ 3 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 tests/sys/netinet/tcp_user_cookie.c diff --git a/cddl/lib/libdtrace/tcp.d b/cddl/lib/libdtrace/tcp.d index 9b27076d809..c5592d26396 100644 --- a/cddl/lib/libdtrace/tcp.d +++ b/cddl/lib/libdtrace/tcp.d @@ -126,6 +126,7 @@ typedef struct tcpsinfo { int tcps_retransmit; /* retransmit send event, boolean */ int tcps_srtt; /* smoothed RTT in units of (TCP_RTT_SCALE*hz) */ int tcps_debug; /* socket has SO_DEBUG set */ + int tcps_cookie; /* expose the socket's SO_USER_COOKIE */ int32_t tcps_dupacks; /* consecutive dup acks received */ uint32_t tcps_rtttime; /* RTT measurement start time */ uint32_t tcps_rtseq; /* sequence # being timed */ @@ -224,6 +225,8 @@ translator tcpsinfo_t < struct tcpcb *p > { tcps_srtt = p == NULL ? -1 : p->t_srtt; /* smoothed RTT in units of (TCP_RTT_SCALE*hz) */ tcps_debug = p == NULL ? 0 : p->t_inpcb->inp_socket->so_options & 1; + tcps_cookie = p == NULL ? -1 : + p->t_inpcb->inp_socket->so_user_cookie; tcps_dupacks = p == NULL ? -1 : p->t_dupacks; tcps_rtttime = p == NULL ? -1 : p->t_rtttime; tcps_rtseq = p == NULL ? -1 : p->t_rtseq; diff --git a/tests/sys/netinet/Makefile b/tests/sys/netinet/Makefile index 14cee19fab9..9e1150ebf61 100644 --- a/tests/sys/netinet/Makefile +++ b/tests/sys/netinet/Makefile @@ -5,7 +5,7 @@ BINDIR= ${TESTSDIR} ATF_TESTS_SH= fibs_test -PROGS= udp_dontroute +PROGS= udp_dontroute tcp_user_cookie MAN= diff --git a/tests/sys/netinet/tcp_user_cookie.c b/tests/sys/netinet/tcp_user_cookie.c new file mode 100644 index 00000000000..162d965ba28 --- /dev/null +++ b/tests/sys/netinet/tcp_user_cookie.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2016 Limelight Networks + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + * + * Authors: George Neville-Neil + * + * $FreeBSD$ + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#define buflen 80 + +/* + * Setup a TCP server listening on a port for connections, all of + * which subseuqently have their user cookie set. + */ +int +main(int argc, char **argv) +{ + struct sockaddr_in srv; + int sock, accepted, port, cookie; + int ret; + char recvbuf[buflen]; + + if (argc != 3) { + fprintf(stderr, "Usage: %s port cookie\n", argv[0]); + exit(2); + } + + port = atoi(argv[1]); + cookie = atoi(argv[2]); + + sock = socket(PF_INET, SOCK_STREAM, 0); + if (sock < 0) + err(EXIT_FAILURE, "socket"); + + srv.sin_len = sizeof(srv); + srv.sin_family = AF_INET; + srv.sin_port = htons(port); + srv.sin_addr.s_addr = INADDR_ANY; + + if (bind(sock, (struct sockaddr *)&srv, srv.sin_len) < 0) + err(EX_OSERR, "failed to bind to port %d", port); + + if (listen(sock, 5) < 0) + err(EX_OSERR, "failed to listen on socket"); + + ret = setsockopt(sock, SOL_SOCKET, SO_USER_COOKIE, &cookie, sizeof(cookie)); + if (ret < 0) + err(EX_OSERR, "setsockopt(SO_USER_COOKIE)"); + + while (1) { + + accepted = accept(sock, NULL, 0); + + if (accepted < 0) + err(EX_OSERR, "accept failed"); + + ret = setsockopt(accepted, SOL_SOCKET, SO_USER_COOKIE, + &cookie, sizeof(cookie)); + if (ret < 0) + err(EX_OSERR, "setsockopt(SO_USER_COOKIE)"); + + ret = read(accepted, &recvbuf, buflen); + + if (ret < 0) + warn("failed read"); + + close(accepted); + } + + return (0); +} -- 2.45.0