tools: add option to include 'LPORT' in tcpconnect otuput (#3301)

add option to include 'LPORT' in tcpconnect otuput and
update man page for tcpconnect and add examples
diff --git a/tools/tcpconnect.py b/tools/tcpconnect.py
index acdf176..0d204ea 100755
--- a/tools/tcpconnect.py
+++ b/tools/tcpconnect.py
@@ -19,6 +19,7 @@
 # 09-Jan-2019   Takuma Kume     Support filtering by UID
 # 30-Jul-2019   Xiaozhou Liu    Count connects.
 # 07-Oct-2020   Nabil Schear    Correlate connects with DNS responses
+# 08-Mar-2021   Suresh Kumar    Added LPORT option
 
 from __future__ import print_function
 from bcc import BPF
@@ -41,6 +42,7 @@
     ./tcpconnect -U        # include UID
     ./tcpconnect -u 1000   # only trace UID 1000
     ./tcpconnect -c        # count connects per src ip and dest ip/port
+    ./tcpconnect -L        # include LPORT while printing outputs
     ./tcpconnect --cgroupmap mappath  # only trace cgroups in this BPF map
     ./tcpconnect --mntnsmap mappath   # only trace mount namespaces in the map
 """
@@ -54,6 +56,8 @@
     help="trace this PID only")
 parser.add_argument("-P", "--port",
     help="comma-separated list of destination ports to trace.")
+parser.add_argument("-L", "--lport", action="store_true",
+    help="include LPORT on output")
 parser.add_argument("-U", "--print-uid", action="store_true",
     help="include UID on output")
 parser.add_argument("-u", "--uid",
@@ -87,6 +91,7 @@
     u32 saddr;
     u32 daddr;
     u64 ip;
+    u16 lport;
     u16 dport;
     char task[TASK_COMM_LEN];
 };
@@ -99,6 +104,7 @@
     unsigned __int128 saddr;
     unsigned __int128 daddr;
     u64 ip;
+    u16 lport;
     u16 dport;
     char task[TASK_COMM_LEN];
 };
@@ -161,6 +167,7 @@
 
     // pull in details
     struct sock *skp = *skpp;
+    u16 lport = skp->__sk_common.skc_num;
     u16 dport = skp->__sk_common.skc_dport;
 
     FILTER_PORT
@@ -202,6 +209,7 @@
                data4.ts_us = bpf_ktime_get_ns() / 1000;
                data4.saddr = skp->__sk_common.skc_rcv_saddr;
                data4.daddr = skp->__sk_common.skc_daddr;
+               data4.lport = lport;
                data4.dport = ntohs(dport);
                bpf_get_current_comm(&data4.task, sizeof(data4.task));
                ipv4_events.perf_submit(ctx, &data4, sizeof(data4));"""
@@ -225,6 +233,7 @@
                    skp->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32);
                bpf_probe_read_kernel(&data6.daddr, sizeof(data6.daddr),
                    skp->__sk_common.skc_v6_daddr.in6_u.u6_addr32);
+               data6.lport = lport;
                data6.dport = ntohs(dport);
                bpf_get_current_comm(&data6.task, sizeof(data6.task));
                ipv6_events.perf_submit(ctx, &data6, sizeof(data6));"""
@@ -354,10 +363,16 @@
     if args.print_uid:
         printb(b"%-6d" % event.uid, nl="")
     dest_ip = inet_ntop(AF_INET, pack("I", event.daddr)).encode()
-    printb(b"%-6d %-12.12s %-2d %-16s %-16s %-6d %s" % (event.pid,
-        event.task, event.ip,
-        inet_ntop(AF_INET, pack("I", event.saddr)).encode(),
-        dest_ip, event.dport, print_dns(dest_ip)))
+    if args.lport:
+        printb(b"%-6d %-12.12s %-2d %-16s %-6d %-16s %-6d %s" % (event.pid,
+            event.task, event.ip,
+            inet_ntop(AF_INET, pack("I", event.saddr)).encode(), event.lport,
+            dest_ip, event.dport, print_dns(dest_ip)))
+    else:
+        printb(b"%-6d %-12.12s %-2d %-16s %-16s %-6d %s" % (event.pid,
+            event.task, event.ip,
+            inet_ntop(AF_INET, pack("I", event.saddr)).encode(),
+            dest_ip, event.dport, print_dns(dest_ip)))
 
 def print_ipv6_event(cpu, data, size):
     event = b["ipv6_events"].event(data)
@@ -369,10 +384,16 @@
     if args.print_uid:
         printb(b"%-6d" % event.uid, nl="")
     dest_ip = inet_ntop(AF_INET6, event.daddr).encode()
-    printb(b"%-6d %-12.12s %-2d %-16s %-16s %-6d %s" % (event.pid,
-        event.task, event.ip,
-        inet_ntop(AF_INET6, event.saddr).encode(), dest_ip,
-        event.dport, print_dns(dest_ip)))
+    if args.lport:
+        printb(b"%-6d %-12.12s %-2d %-16s %-6d %-16s %-6d %s" % (event.pid,
+            event.task, event.ip,
+            inet_ntop(AF_INET6, event.saddr).encode(), event.lport,
+            dest_ip, event.dport, print_dns(dest_ip)))
+    else:
+        printb(b"%-6d %-12.12s %-2d %-16s %-16s %-6d %s" % (event.pid,
+            event.task, event.ip,
+            inet_ntop(AF_INET6, event.saddr).encode(),
+            dest_ip, event.dport, print_dns(dest_ip)))
 
 def depict_cnt(counts_tab, l3prot='ipv4'):
     for k, v in sorted(counts_tab.items(),
@@ -490,8 +511,12 @@
         print("%-9s" % ("TIME(s)"), end="")
     if args.print_uid:
         print("%-6s" % ("UID"), end="")
-    print("%-6s %-12s %-2s %-16s %-16s %-6s" % ("PID", "COMM", "IP", "SADDR",
-        "DADDR", "DPORT"), end="")
+    if args.lport:
+        print("%-6s %-12s %-2s %-16s %-6s %-16s %-6s" % ("PID", "COMM", "IP", "SADDR",
+            "LPORT", "DADDR", "DPORT"), end="")
+    else:
+        print("%-6s %-12s %-2s %-16s %-16s %-6s" % ("PID", "COMM", "IP", "SADDR",
+            "DADDR", "DPORT"), end="")
     if args.dns:
         print(" QUERY")
     else:
diff --git a/tools/tcpconnect_example.txt b/tools/tcpconnect_example.txt
index b8ad22d..f2e6d72 100644
--- a/tools/tcpconnect_example.txt
+++ b/tools/tcpconnect_example.txt
@@ -55,6 +55,15 @@
 2015   ssh          6  fe80::2000:bff:fe82:3ac fe80::2000:bff:fe82:3ac 22    anotherhost.org
 
 
+The -L option prints a LPORT column:
+
+# ./tcpconnect -L
+PID    COMM         IP SADDR            LPORT  DADDR            DPORT
+3706   nc           4  192.168.122.205  57266  192.168.122.150  5000
+3722   ssh          4  192.168.122.205  50966  192.168.122.150  22
+3779   ssh          6  fe80::1          52328  fe80::2          22
+
+
 The -U option prints a UID column:
 
 # ./tcpconnect -U
@@ -97,7 +106,7 @@
 
 # ./tcpconnect -h
 
-usage: tcpconnect.py [-h] [-t] [-p PID] [-P PORT] [-U] [-u UID] [-c]
+usage: tcpconnect.py [-h] [-t] [-p PID] [-P PORT] [-L] [-U] [-u UID] [-c]
                      [--cgroupmap CGROUPMAP] [--mntnsmap MNTNSMAP] [-d]
 
 Trace TCP connects
@@ -107,6 +116,7 @@
   -t, --timestamp       include timestamp on output
   -p PID, --pid PID     trace this PID only
   -P PORT, --port PORT  comma-separated list of destination ports to trace.
+  -L, --lport           include LPORT on output
   -U, --print-uid       include UID on output
   -u UID, --uid UID     trace this UID only
   -c, --count           count connects per src ip and dest ip/port
@@ -118,11 +128,13 @@
 examples:
     ./tcpconnect           # trace all TCP connect()s
     ./tcpconnect -t        # include timestamps
+    ./tcpconnect -d        # include DNS queries associated with connects
     ./tcpconnect -p 181    # only trace PID 181
     ./tcpconnect -P 80     # only trace port 80
     ./tcpconnect -P 80,81  # only trace port 80 and 81
     ./tcpconnect -U        # include UID
     ./tcpconnect -u 1000   # only trace UID 1000
     ./tcpconnect -c        # count connects per src ip and dest ip/port
+    ./tcpconnect -L        # include LPORT while printing outputs
     ./tcpconnect --cgroupmap mappath  # only trace cgroups in this BPF map
-    ./tcpconnect --mntnsmap mappath   # only trace mount namespaces in the map
\ No newline at end of file
+    ./tcpconnect --mntnsmap mappath   # only trace mount namespaces in the map