Re: SO_BINDTODEVICE or sendto using specific network interface
Re: SO_BINDTODEVICE or sendto using specific network interface
- Subject: Re: SO_BINDTODEVICE or sendto using specific network interface
- From: "Peter Sichel" <email@hidden>
- Date: Thu, 15 Dec 2005 10:10:11 -0500
On 12/14/05, Alex Telitsine wrote:
>Peter,
>
>I was able to send UDP independently on each interface via BPF.
>Right now I have to specify each router MAC address, so IP/Ethernet
>packets are properly created end delivered. There are 2 main problems
>left to solve: automatically obtain MAC address for the routers
>( should be possible with ARP) and gain "root" privilege for PFB
>access in .APP/GUI mode.
>
>I would like multi-path to be integrated into the packge. But it is
>possible we'll need to use 3rd party plugin, if there is problem with
>"root" access right for BPF mode.
This is now a pretty well understood problem, but not easily
grokked at first.
The way I do this is to use a tiny helper applet that opens a BPF
socket and returns it using BSD descriptor passing. By making this
program SUID root, the rest of the application does not require
root privileges.
The helper applet is configured as SUID root the first time
the main application is launched using AuthorizeExecuteWithPriveleges()
to launch another helper app that configures file permissions so
the installer is effectively built-in to the app itself. The
alternative is to create a separate installer to install your
helper somewhere with the correct file permissions (but I
prefer drag-and-drop installation).
----
// Open a raw socket and return it using BSD Descriptor Passing.
// By making this tiny program SUID root, a non-privileged application
// can gain access to raw sockets.
//
// The caller opens a stream pipe, maps the pipe to be our
// STDIN and STDOUT, and then does a fork followed by exec.
// We just open a raw socket and return it via sendmsg to STDOUT_FILENO.
//
// A future version could use command line arguments to specify
// what type of socket is desired.
int
main(int argc, char* argv[])
{
int newfd;
int result;
...
else if (argc == 2 && !strcmp(argv[1], "-bpf")) {
// assume we are executing as SUID root
// get a bpf_fd for sending raw Ethernet or Firewire frames
newfd = bpf_new();
if ( SendFD(STDOUT_FILENO, newfd ) == 0 ) {
perror( "failed to send fd" );
return 1;
}
if (newfd > 0) close(newfd); // we're done with descriptor
}
return 0;
}
int
SendFD( int channel, int fd )
{
char buff[kFDSize];
struct iovec iov[1];
struct msghdr msg = {0};
struct data {
struct cmsghdr cmsg;
int fd;
} data;
int struct_data_size = sizeof(struct cmsghdr) + sizeof(int);
memset( &data, 0, sizeof( data ));
iov[0].iov_base = buff;
iov[0].iov_len = kFDSize;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
data.cmsg.cmsg_level = SOL_SOCKET;
data.cmsg.cmsg_type = SCM_RIGHTS;
data.cmsg.cmsg_len = struct_data_size;
data.fd = fd;
msg.msg_control = (caddr_t) &data;
msg.msg_controllen = struct_data_size;
// [PAS] interpret negative fd as resultCode and send it in msg buff
bzero(buff, kFDSize);
if (fd < 0) {
data.fd = 0;
memcpy(buff, &fd, kFDSize);
}
if ( sendmsg( channel, &msg, 0 ) == -1 ) return 0;
return 1;
}
int
ReceiveFD( int channel )
{
char buff[kFDSize];
int fd = 0;
struct iovec iov[1];
struct msghdr msg = {0};
int resultCode;
struct data {
struct cmsghdr cmsg;
int fd;
char padding[12];
} data;
memset( &data, 0, sizeof( data ));
iov[0].iov_base = buff;
iov[0].iov_len = kFDSize;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
msg.msg_control = (caddr_t) &data;
msg.msg_controllen = sizeof( struct data );
if ( recvmsg( channel, &msg, 0 ) == -1 ) return -1;
fd = data.fd;
if( (uint32_t) msg.msg_controllen < sizeof( struct cmsghdr ) +
sizeof( int )) {
errno = EIO; // bit vague I know...
return -1;
}
// [PAS] if buff is <0 pass back as result code
memcpy(&resultCode, &buff, kFDSize);
if (resultCode < 0) fd = resultCode;
return fd;
}
int
bpf_new()
{
char bpfdev[256];
int i;
int fd = -1;
for (i = 0; 1; i++) {
sprintf(bpfdev, "/dev/bpf%d", i);
fd = open(bpfdev, O_RDWR , 0);
if (fd >= 0) break;
if (errno != EBUSY) break;
}
return (fd);
}
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Macnetworkprog mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden