1

I am trying to set up a SilverLight policy server under MacOSX 10.7.2 (Lion). This requires that I create and bind a socket to port 943, since SilverLight requests the policy file on this port. Unfortunately, it seems I am unable to bind at that port, as the bind call fails with errno=49. I suppose I do not have access to this port. Perhaps I need root privileges? Or do I need to forward this port to another one that I can bind? I'm a bit new to network programming, so any help is greatly appreciated! I've also attached my source code. Perhaps I'm doing something wrong, although it works fine if I use the SilverLight restricted ports 4502-4532, which SilverLight communicates on once the policy file is successfully served.

- (void) start {
    CFSocketRef socket = CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_STREAM, IPPROTO_TCP, 0, NULL, NULL);
    if (!socket) {
        [self errorWithName:@"Unable to create socket."];
        return;
    }

    int reuse = true;
    CFSocketNativeHandle fileDescriptor = CFSocketGetNative(socket);
    if (setsockopt(fileDescriptor, SOL_SOCKET, SO_REUSEADDR,
                   (void *)&reuse, sizeof(int)) != 0) {
        NSLog(@"Unable to set socket options.");
        return;
    }

    struct sockaddr_in address;
    memset(&address, 0, sizeof(address));
    address.sin_len = sizeof(address);
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    address.sin_port = htons(943);
    CFDataRef addressData = CFDataCreate(NULL, (const UInt8 *)&address, sizeof(address));
    [(id)addressData autorelease];

    CFSocketError error = CFSocketSetAddress(socket, addressData);
    if (error < 0) {
        NSLog(@"Error bind %d\n", errno);  //fails here for port 943.
        return;
    }

    NSFileHandle *listeningHandle = [[NSFileHandle alloc]
                   initWithFileDescriptor:fileDescriptor
                   closeOnDealloc:YES];

    [[NSNotificationCenter defaultCenter]
          addObserver:self
             selector:@selector(receiveIncomingConnectionNotification:)
                 name:NSFileHandleConnectionAcceptedNotification
               object:nil];

    [listeningHandle acceptConnectionInBackgroundAndNotify];
}
Tal
  • 422
  • 3
  • 13
Peter Jacobs
  • 1,657
  • 2
  • 13
  • 29

1 Answers1

3

Only root has privileges for ports below 1024. Try running your code with sudo and see if that fixes your issue.

Edit:

Also, check out man strerror. It will take that relatively meaningless error code and give you a (slightly) more useful string.

#include <stdio.h>
#include <string.h>

int main (int argc, char const *argv[])
{
  printf("%s\n", strerror(49) );
  return 0;
}

Gives:

Can't assign requested address
James
  • 2,373
  • 18
  • 16
  • Thanks! Yes, if I run it with sudo, it no longer fails. Also, I found out that I must first zero out the sockaddr_in struct and set the sin_len field. Then, prior to running it with sudo, I was actually getting errno=13, which is permission denied. Thanks again for your response. – Peter Jacobs Nov 20 '11 at 01:32
  • No problem -- since this worked for you, you can accept my answer so others can more easily find the solution. – James Nov 20 '11 at 01:36
  • Absolutely... I selected the green checkmark, which I assume does the trick. However, I wonder if there is a way to accomplish this without having root access. For example, perhaps by doing some kind of forwarding of port 943 to one that does not require root access? – Peter Jacobs Nov 20 '11 at 02:12