mirror of
https://git.rtems.org/rtems-libbsd/
synced 2025-06-05 17:00:21 +08:00

The sources can be obtained via: https://opensource.apple.com/tarballs/mDNSResponder/mDNSResponder-765.1.2.tar.gz Move mDNS_StartResolveService() and mDNS_StopResolveService() to an RTEMS-specific file (rtemsbsd/mdns/mDNSResolveService.c) using the v576.30.4 implementation. Apple removed these functions without explanation. Update #3522.
302 lines
7.6 KiB
C
302 lines
7.6 KiB
C
/* -*- Mode: C; tab-width: 4 -*-
|
|
*
|
|
* Copyright (c) 2011 Apple Inc. All rights reserved.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include <net/if.h>
|
|
#include <System/net/pfvar.h>
|
|
#include <string.h>
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
#include <sys/ioctl.h>
|
|
#include <unistd.h>
|
|
#include <AssertMacros.h>
|
|
#include "P2PPacketFilter.h"
|
|
|
|
#define AIRDROP_ANCHOR_PATH "com.apple/200.AirDrop"
|
|
#define MDNS_ANCHOR_NAME "Bonjour"
|
|
#define MDNS_ANCHOR_PATH AIRDROP_ANCHOR_PATH "/" MDNS_ANCHOR_NAME
|
|
|
|
#define PF_DEV_PATH "/dev/pf"
|
|
#define BONJOUR_PORT 5353
|
|
|
|
static int openPFDevice( int * outFD )
|
|
{
|
|
int err;
|
|
int fd = open( PF_DEV_PATH, O_RDWR );
|
|
|
|
if( fd >= 0 )
|
|
{
|
|
err = 0;
|
|
*outFD = fd;
|
|
}
|
|
else
|
|
{
|
|
err = errno;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
static int getTicket( int devFD, u_int32_t * outTicket, char * anchorPath )
|
|
{
|
|
struct pfioc_trans_e trans_e;
|
|
|
|
trans_e.rs_num = PF_RULESET_FILTER;
|
|
strlcpy( trans_e.anchor, anchorPath, sizeof( trans_e.anchor ) );
|
|
|
|
struct pfioc_trans trans;
|
|
|
|
trans.size = 1;
|
|
trans.esize = sizeof( trans_e );
|
|
trans.array = &trans_e;
|
|
|
|
int result, ioctlError;
|
|
|
|
ioctlError = ioctl( devFD, DIOCXBEGIN, &trans );
|
|
if( ioctlError )
|
|
{
|
|
result = errno;
|
|
}
|
|
else
|
|
{
|
|
result = 0;
|
|
*outTicket = trans_e.ticket;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static int commitChange( int devFD, u_int32_t ticket, char * anchorPath )
|
|
{
|
|
struct pfioc_trans_e trans_e;
|
|
|
|
trans_e.rs_num = PF_RULESET_FILTER;
|
|
strlcpy( trans_e.anchor, anchorPath, sizeof( trans_e.anchor ) );
|
|
trans_e.ticket = ticket;
|
|
|
|
struct pfioc_trans trans;
|
|
|
|
trans.size = 1;
|
|
trans.esize = sizeof( trans_e );
|
|
trans.array = &trans_e;
|
|
|
|
int result, ioctlError;
|
|
|
|
ioctlError = ioctl( devFD, DIOCXCOMMIT, &trans );
|
|
if( ioctlError )
|
|
result = errno;
|
|
else
|
|
result = 0;
|
|
|
|
return result;
|
|
}
|
|
|
|
static int getPoolTicket( int devFD, u_int32_t * outPoolTicket )
|
|
{
|
|
struct pfioc_pooladdr pp;
|
|
|
|
int result, ioctlError;
|
|
|
|
ioctlError = ioctl( devFD, DIOCBEGINADDRS, &pp );
|
|
if( ioctlError )
|
|
{
|
|
result = errno;
|
|
}
|
|
else
|
|
{
|
|
result = 0;
|
|
*outPoolTicket = pp.ticket;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static int addRule( int devFD, struct pfioc_rule * pr )
|
|
{
|
|
int result, ioctlResult;
|
|
|
|
ioctlResult = ioctl( devFD, DIOCADDRULE, pr );
|
|
if( ioctlResult )
|
|
result = errno;
|
|
else
|
|
result = 0;
|
|
|
|
return result;
|
|
}
|
|
|
|
static void initRuleHeader( struct pfioc_rule * pr,
|
|
u_int32_t ticket,
|
|
u_int32_t poolTicket,
|
|
char * anchorPath )
|
|
{
|
|
pr->action = PF_CHANGE_NONE;
|
|
pr->ticket = ticket;
|
|
pr->pool_ticket = poolTicket;
|
|
strlcpy( pr->anchor, anchorPath, sizeof( pr->anchor ) );
|
|
}
|
|
|
|
// allow inbound traffice on the Bonjour port (5353)
|
|
static void initBonjourRule( struct pfioc_rule * pr,
|
|
const char * interfaceName,
|
|
u_int32_t ticket,
|
|
u_int32_t poolTicket,
|
|
char * anchorPath )
|
|
{
|
|
memset( pr, 0, sizeof( *pr ) );
|
|
|
|
// Header
|
|
initRuleHeader( pr, ticket, poolTicket, anchorPath );
|
|
|
|
// Rule
|
|
pr->rule.dst.xport.range.port[0] = htons( BONJOUR_PORT );
|
|
pr->rule.dst.xport.range.op = PF_OP_EQ;
|
|
|
|
strlcpy( pr->rule.ifname, interfaceName, sizeof( pr->rule.ifname ) );
|
|
|
|
pr->rule.action = PF_PASS;
|
|
pr->rule.direction = PF_IN;
|
|
pr->rule.keep_state = 1;
|
|
pr->rule.af = AF_INET6;
|
|
pr->rule.proto = IPPROTO_UDP;
|
|
pr->rule.extfilter = PF_EXTFILTER_APD;
|
|
}
|
|
|
|
// allow outbound TCP connections and return traffic for those connections
|
|
static void initOutboundTCPRule( struct pfioc_rule * pr,
|
|
const char * interfaceName,
|
|
u_int32_t ticket,
|
|
u_int32_t poolTicket,
|
|
char * anchorPath )
|
|
{
|
|
memset( pr, 0, sizeof( *pr ) );
|
|
|
|
// Header
|
|
initRuleHeader( pr, ticket, poolTicket, anchorPath );
|
|
|
|
// Rule
|
|
strlcpy( pr->rule.ifname, interfaceName, sizeof( pr->rule.ifname ) );
|
|
|
|
pr->rule.action = PF_PASS;
|
|
pr->rule.direction = PF_OUT;
|
|
pr->rule.keep_state = 1;
|
|
pr->rule.proto = IPPROTO_TCP;
|
|
}
|
|
|
|
// allow inbound traffic on the specified port and protocol
|
|
static void initPortRule( struct pfioc_rule * pr,
|
|
const char * interfaceName,
|
|
u_int32_t ticket,
|
|
u_int32_t poolTicket,
|
|
char * anchorPath,
|
|
u_int16_t port,
|
|
u_int16_t protocol )
|
|
{
|
|
memset( pr, 0, sizeof( *pr ) );
|
|
|
|
// Header
|
|
initRuleHeader( pr, ticket, poolTicket, anchorPath );
|
|
|
|
// Rule
|
|
// mDNSResponder passes the port in Network Byte Order, so htons(port) is not required
|
|
pr->rule.dst.xport.range.port[0] = port;
|
|
pr->rule.dst.xport.range.op = PF_OP_EQ;
|
|
|
|
strlcpy( pr->rule.ifname, interfaceName, sizeof( pr->rule.ifname ) );
|
|
|
|
pr->rule.action = PF_PASS;
|
|
pr->rule.direction = PF_IN;
|
|
pr->rule.keep_state = 1;
|
|
pr->rule.af = AF_INET6;
|
|
pr->rule.proto = protocol;
|
|
pr->rule.extfilter = PF_EXTFILTER_APD;
|
|
}
|
|
|
|
// allow inbound traffic on the Bonjour port (5353) and the specified port and protocol sets
|
|
int P2PPacketFilterAddBonjourRuleSet(const char * interfaceName, u_int32_t count, pfArray_t portArray, pfArray_t protocolArray )
|
|
{
|
|
int result;
|
|
u_int32_t i;
|
|
u_int32_t ticket = 0;
|
|
u_int32_t poolTicket = 0;
|
|
int devFD = -1;
|
|
char * anchorPath = MDNS_ANCHOR_PATH;
|
|
|
|
result = openPFDevice( &devFD );
|
|
require( result == 0, exit );
|
|
|
|
result = getTicket( devFD, &ticket, anchorPath );
|
|
require( result == 0, exit );
|
|
|
|
result = getPoolTicket( devFD, &poolTicket );
|
|
require( result == 0, exit );
|
|
|
|
struct pfioc_rule pr;
|
|
|
|
// allow inbound Bonjour traffice to port 5353
|
|
initBonjourRule( &pr, interfaceName, ticket, poolTicket, anchorPath);
|
|
|
|
result = addRule( devFD, &pr );
|
|
require( result == 0, exit );
|
|
|
|
// open inbound port for each service
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
initPortRule( &pr, interfaceName, ticket, poolTicket, anchorPath, portArray[i], protocolArray[i] );
|
|
result = addRule( devFD, &pr );
|
|
require( result == 0, exit );
|
|
}
|
|
|
|
// allow outbound TCP connections and return traffic for those connections
|
|
initOutboundTCPRule( &pr, interfaceName, ticket, poolTicket, anchorPath);
|
|
|
|
result = addRule( devFD, &pr );
|
|
require( result == 0, exit );
|
|
|
|
result = commitChange( devFD, ticket, anchorPath );
|
|
require( result == 0, exit );
|
|
|
|
exit:
|
|
|
|
if( devFD >= 0 )
|
|
close( devFD );
|
|
|
|
return result;
|
|
}
|
|
|
|
int P2PPacketFilterClearBonjourRules()
|
|
{
|
|
int result;
|
|
int pfDev = -1;
|
|
u_int32_t ticket = 0;
|
|
char * anchorPath = MDNS_ANCHOR_PATH;
|
|
|
|
result = openPFDevice( &pfDev );
|
|
require( result == 0, exit );
|
|
|
|
result = getTicket( pfDev, &ticket, anchorPath );
|
|
require( result == 0, exit );
|
|
|
|
result = commitChange( pfDev, ticket, anchorPath );
|
|
|
|
exit:
|
|
|
|
if( pfDev >= 0 )
|
|
close( pfDev );
|
|
|
|
return result;
|
|
}
|
|
|