diff --git a/include/globvar.h b/include/globvar.h
index 63c7e07..db999fc 100644
--- a/include/globvar.h
+++ b/include/globvar.h
@@ -48,6 +48,8 @@ struct fs_context {
/* -x */ uint32_t fwmask;
/* -y */ int dynamic_pct;
/* -z */ int use_iptables;
+ /* -p */ uint8_t *port_white;
+ /* -P */ uint8_t *port_black;
};
extern struct fs_context g_ctx;
diff --git a/include/portmap.h b/include/portmap.h
new file mode 100644
index 0000000..e27b2fe
--- /dev/null
+++ b/include/portmap.h
@@ -0,0 +1,31 @@
+/*
+ * portmap.h - FakeSIP: https://github.com/MikeWang000000/FakeSIP
+ *
+ * Copyright (C) 2025 MikeWang000000
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef FS_PORTMAP_H
+#define FS_PORTMAP_H
+
+#include
+
+int fs_portmap_get(const uint8_t *bitmap, uint16_t port);
+
+void fs_portmap_set(uint8_t *bitmap, uint16_t port);
+
+int fs_portmap_parse(uint8_t **bitmap_ptr, const char *spec);
+
+#endif /* FS_PORTMAP_H */
diff --git a/src/globvar.c b/src/globvar.c
index 4abeada..7ebe786 100644
--- a/src/globvar.c
+++ b/src/globvar.c
@@ -45,4 +45,6 @@ struct fs_context g_ctx = {.exit = 0,
/* -w */ .logpath = NULL,
/* -x */ .fwmask = 0,
/* -y */ .dynamic_pct = 0,
- /* -z */ .use_iptables = 0};
+ /* -z */ .use_iptables = 0,
+ /* -p */ .port_white = NULL,
+ /* -P */ .port_black = NULL};
diff --git a/src/mainfun.c b/src/mainfun.c
index 9bc9a7a..81020d6 100644
--- a/src/mainfun.c
+++ b/src/mainfun.c
@@ -41,6 +41,7 @@
#include "rawsend.h"
#include "signals.h"
#include "srcinfo.h"
+#include "portmap.h"
#ifndef PROGNAME
#define PROGNAME "fakesip"
@@ -73,6 +74,10 @@ static void print_usage(const char *name)
" -s enable silent mode\n"
" -w write log to instead of stderr\n"
"\n"
+ "Port Filters:\n"
+ " -p comma-separated whitelist ports eq 53,80-1000\n"
+ " -P comma-separated blacklist ports eq 51820,51413\n"
+ "\n"
"Advanced Options:\n"
" -f skip firewall rules\n"
" -g disable hop count estimation\n"
@@ -124,7 +129,7 @@ int main(int argc, char *argv[])
plinfo_cnt = iface_cnt = 0;
- while ((opt = getopt(argc, argv, "0146ab:dfgi:km:n:r:st:u:w:x:y:z")) !=
+ while ((opt = getopt(argc, argv, "0146ab:dfgi:km:n:r:st:u:w:x:y:zp:P:")) !=
-1) {
switch (opt) {
case '0':
@@ -278,6 +283,30 @@ int main(int argc, char *argv[])
}
break;
+ case 'p':
+ case 'P': {
+ if (!optarg[0]) {
+ fprintf(stderr, "%s: value of -%c cannot be empty.\n",
+ argv[0], opt);
+ print_usage(argv[0]);
+ goto free_mem;
+ }
+
+ if (opt == 'p') {
+ if (fs_portmap_parse(&g_ctx.port_white, optarg) < 0) {
+ fprintf(stderr, "%s: invalid port spec for -p: %s\n",
+ argv[0], optarg);
+ goto free_mem;
+ }
+ } else {
+ if (fs_portmap_parse(&g_ctx.port_black, optarg) < 0) {
+ fprintf(stderr, "%s: invalid port spec for -P: %s\n",
+ argv[0], optarg);
+ goto free_mem;
+ }
+ }
+ } break;
+
case 'x':
tmp = strtoull(optarg, NULL, 0);
if (!tmp || tmp > UINT32_MAX) {
@@ -490,5 +519,13 @@ int main(int argc, char *argv[])
free(g_ctx.iface);
}
+ if (g_ctx.port_white) {
+ free(g_ctx.port_white);
+ }
+
+ if (g_ctx.port_black) {
+ free(g_ctx.port_black);
+ }
+
return exitcode;
}
diff --git a/src/portmap.c b/src/portmap.c
new file mode 100644
index 0000000..5d2ca2d
--- /dev/null
+++ b/src/portmap.c
@@ -0,0 +1,99 @@
+/*
+ * portmap.c - FakeSIP: https://github.com/MikeWang000000/FakeSIP
+ *
+ * Copyright (C) 2025 MikeWang000000
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#define _GNU_SOURCE
+#include "portmap.h"
+
+#include
+#include
+#include
+#include
+
+int fs_portmap_parse(uint8_t **bitmap_ptr, const char *spec)
+{
+ char *sdup = NULL, *tok, *saveptr;
+ int ret = -1;
+
+ if (!spec || !spec[0]) {
+ return -1;
+ }
+
+ sdup = strdup(spec);
+ if (!sdup)
+ return -1;
+
+ for (tok = strtok_r(sdup, ",", &saveptr); tok;
+ tok = strtok_r(NULL, ",", &saveptr)) {
+ char *dash = strchr(tok, '-');
+ unsigned long start, end;
+ char *endptr;
+
+ if (!dash) {
+ start = strtoul(tok, &endptr, 0);
+ if (endptr == tok || *endptr != '\0' || start == 0 ||
+ start > 65535) {
+ goto out;
+ }
+ end = start;
+ } else {
+ *dash = '\0';
+ start = strtoul(tok, &endptr, 0);
+ if (endptr == tok || *endptr != '\0' || start == 0 ||
+ start > 65535) {
+ goto out;
+ }
+ end = strtoul(dash + 1, &endptr, 0);
+ if (endptr == dash + 1 || *endptr != '\0' || end == 0 ||
+ end > 65535) {
+ goto out;
+ }
+ if (start > end)
+ goto out;
+ }
+
+ if (!*bitmap_ptr) {
+ *bitmap_ptr = calloc(1, 8192);
+ if (!*bitmap_ptr)
+ goto out;
+ }
+
+ for (unsigned long p = start; p <= end; p++) {
+ fs_portmap_set(*bitmap_ptr, (uint16_t) p);
+ }
+ }
+
+ ret = 0;
+out:
+ free(sdup);
+ return ret;
+}
+
+int fs_portmap_get(const uint8_t *bitmap, uint16_t port)
+{
+ if (!bitmap)
+ return 0;
+ return (bitmap[port >> 3] & (uint8_t) (1u << (port & 7))) ? 1 : 0;
+}
+
+void fs_portmap_set(uint8_t *bitmap, uint16_t port)
+{
+ if (!bitmap)
+ return;
+ bitmap[port >> 3] |= (uint8_t) (1u << (port & 7));
+}
diff --git a/src/rawsend.c b/src/rawsend.c
index 5bcb0ef..dc8e858 100644
--- a/src/rawsend.c
+++ b/src/rawsend.c
@@ -39,6 +39,7 @@
#include "logging.h"
#include "payload.h"
#include "srcinfo.h"
+#include "portmap.h"
#define NO_SNAT 0
#define NEED_SNAT 1
@@ -375,6 +376,36 @@ int fs_rawsend_handle(struct sockaddr_ll *sll, uint8_t *pkt_data, int pkt_len,
ipaddr_to_str(daddr, dst_ip_str);
}
+ /* Port whitelist/blacklist filtering: if whitelist is set, only process
+ packets where either source or dest port is in the whitelist. If any
+ port matches the blacklist, skip processing. */
+ {
+ uint16_t sport = ntohs(udph->source);
+ uint16_t dport = ntohs(udph->dest);
+
+ if (g_ctx.port_white) {
+ if (!(fs_portmap_get(g_ctx.port_white, sport) ||
+ fs_portmap_get(g_ctx.port_white, dport))) {
+ if (!g_ctx.silent) {
+ E_INFO("%s:%u ===(SKIP)=== %s:%u", src_ip_str, sport,
+ dst_ip_str, dport);
+ }
+ return NF_ACCEPT;
+ }
+ }
+
+ if (g_ctx.port_black) {
+ if (fs_portmap_get(g_ctx.port_black, sport) ||
+ fs_portmap_get(g_ctx.port_black, dport)) {
+ if (!g_ctx.silent) {
+ E_INFO("%s:%u ===(SKIP)=== %s:%u", src_ip_str, sport,
+ dst_ip_str, dport);
+ }
+ return NF_ACCEPT;
+ }
+ }
+ }
+
if (sll->sll_pkttype == PACKET_HOST) {
/*
Inbound UDP packet.