#!/usr/bin/env bash
# docker_ports_used.sh
# Liste unique des ports utilisés avec protocole + service/container associé(s), triés par port.
# Doit être exécuté en root → relance automatiquement avec sudo si nécessaire.

set -euo pipefail

# ---- Vérif des droits root ----
if [ "$(id -u)" -ne 0 ]; then
  echo "⚠️  Ce script doit être exécuté en root. Relance avec sudo..."
  exec sudo "$0" "$@"
fi

tmpfile=$(mktemp)

# ---- Docker ports -> container ----
docker ps --format '{{.Names}} {{.Ports}}' 2>/dev/null |
while read -r name ports; do
  [ -z "${ports:-}" ] && continue
  echo "$ports" | tr ',' '\n' | while read -r mapping; do
    host_port=$(echo "$mapping" | sed -n 's/.*:\([0-9]\+\)->.*/\1/p')
    proto=$(echo "$mapping" | sed -n 's/.*->.*\/\(tcp\|udp\).*/\1/p')
    if [ -n "$host_port" ]; then
      [ -z "$proto" ] && proto="tcp"
      echo "$host_port $proto $name(container)"
    fi
  done
done >>"$tmpfile" || true

# ---- System ports -> process ----
if command -v ss >/dev/null 2>&1; then
  # TCP
  ss -ltnp 2>/dev/null | awk 'NR>1 {print $1,$4,$6}' |
  while read -r proto addr proc; do
    port=$(echo "$addr" | sed -E 's/.*:([0-9]+)$/\1/')
    procname=$(echo "$proc" | sed -n 's/.*"\(.*\)".*/\1/p')
    [ -z "$procname" ] && procname="(unknown)"
    [ -n "$port" ] && echo "$port tcp $procname"
  done >>"$tmpfile"

  # UDP
  ss -lunp 2>/dev/null | awk 'NR>1 {print $1,$4,$6}' |
  while read -r proto addr proc; do
    port=$(echo "$addr" | sed -E 's/.*:([0-9]+)$/\1/')
    procname=$(echo "$proc" | sed -n 's/.*"\(.*\)".*/\1/p')
    [ -z "$procname" ] && procname="(unknown)"
    [ -n "$port" ] && echo "$port udp $procname"
  done >>"$tmpfile"

elif command -v netstat >/dev/null 2>&1; then
  netstat -ltnp 2>/dev/null | awk 'NR>2 {split($4,a,":"); port=a[length(a)]; split($7,b,"/"); print port,"tcp",b[2]}' >>"$tmpfile"
  netstat -lunp 2>/dev/null | awk 'NR>2 {split($4,a,":"); port=a[length(a)]; split($7,b,"/"); print port,"udp",b[2]}' >>"$tmpfile"
fi

# ---- Fusion + tri ----
awk '
{
  port=$1; proto=$2; $1=""; $2="";
  desc=substr($0,3)
  if (desc=="" || desc=="-") desc="(unknown)"
  key=port" "proto
  if (map[key]!="") {
    if (index(map[key], desc)==0) {
      map[key]=map[key]", "desc
    }
  } else {
    map[key]=desc
  }
}
END {
  for (k in map) {
    split(k,a," ")
    port=a[1]; proto=a[2]
    printf "%-6s %-4s %s\n", port, proto, map[k]
  }
}' "$tmpfile" | sort -n -k1,1

rm -f "$tmpfile"