+// Some processes, due to particular entitlements, require using an NECP client to
+// access networking. Returns true if the result should be a Drop.
+static inline bool
+necp_check_missing_client_drop(proc_t proc, struct necp_socket_info *info)
+{
+ task_t task = proc_task(proc ? proc : current_proc());
+
+ if (!info->has_client &&
+ task != NULL &&
+ IOTaskHasEntitlement(task, "com.apple.developer.on-demand-install-capable")) {
+ // Drop connections that don't use NECP clients and have the
+ // com.apple.developer.on-demand-install-capable entitlement.
+ // This effectively restricts those processes to only using
+ // an NECP-aware path for networking.
+ return true;
+ } else {
+ return false;
+ }
+}
+
+static inline bool
+necp_check_restricted_multicast_drop(proc_t proc, struct necp_socket_info *info, bool check_minor_version)
+{
+ if (!necp_restrict_multicast || proc == NULL) {
+ return false;
+ }
+
+ // Check for multicast/broadcast here
+ if (info->remote_addr.sa.sa_family == AF_INET) {
+ if (!IN_MULTICAST(ntohl(info->remote_addr.sin.sin_addr.s_addr)) &&
+ info->remote_addr.sin.sin_addr.s_addr != INADDR_BROADCAST) {
+ return false;
+ }
+ } else if (info->remote_addr.sa.sa_family == AF_INET6) {
+ if (!IN6_IS_ADDR_MULTICAST(&info->remote_addr.sin6.sin6_addr)) {
+ return false;
+ }
+ } else {
+ // Not IPv4/IPv6
+ return false;
+ }
+
+ if (necp_is_platform_binary(proc)) {
+ return false;
+ }
+
+ const uint32_t platform = proc_platform(proc);
+ const uint32_t sdk = proc_sdk(proc);
+
+ // Enforce for iOS, linked on or after version 14
+ // If the caller set `check_minor_version`, only enforce starting at 14.TBD
+ if (platform != PLATFORM_IOS ||
+ sdk == 0 ||
+ (sdk >> 16) < 14 ||
+#if 0
+ (check_minor_version && (sdk >> 16) == 14 && ((sdk >> 8) & 0xff) < TBD)) {
+#else
+ (check_minor_version)) {
+#endif
+ return false;
+ }
+
+ // Allow entitled processes to use multicast
+ task_t task = proc_task(proc);
+ if (task != NULL &&
+ IOTaskHasEntitlement(task, "com.apple.developer.networking.multicast")) {
+ return false;
+ }
+
+ const uint32_t min_sdk = proc_min_sdk(proc);
+ NECPLOG(LOG_INFO, "Dropping unentitled multicast (SDK 0x%x, min 0x%x)", sdk, min_sdk);
+
+ return true;
+}
+