*BSD News Article 52657


Return to BSD News archive

Path: euryale.cc.adfa.oz.au!newshost.anu.edu.au!harbinger.cc.monash.edu.au!msunews!news.mtu.edu!newsxfer.itd.umich.edu!news.mathworks.com!uunet!in2.uu.net!EU.net!sun4nl!sci.kun.nl!polder.ubc.kun.nl!rhialto
From: rhialto@polder.ubc.kun.nl (Olaf Seibert)
Newsgroups: comp.unix.bsd.netbsd.misc
Subject: bind()ing a socket to a specific address?
Date: 5 Oct 1995 17:04:24 GMT
Organization: University of Nijmegen, The Netherlands
Lines: 121
Message-ID: <45136o$6qf@wn1.sci.kun.nl>
NNTP-Posting-Host: polder.ubc.kun.nl
Organisation: Polderland Language & Speech Technology

I am trying to bind() a socket to a specific IP address, but I always
get the error EADDRNOTAVAIL: "Can't assign requested address".
Nevertheless, as far as I can see, this should be possible.
The only address that will work is INADDR_ANY (i.e., 0.0.0.0).

I took a quick look in the kernel sources, and what I saw should also
allow it.

Any hints? I have appended source of my program (not very long).
Try it with command line such as a.out localhost 1234 (does not work)
or a.out 0 1234 (does work but is not what I want).

NB: This is with NetBSD/i386 1.0 but that should hardly make a
difference.

#include <stdio.h>
#include <errno.h>
#include <ctype.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

int one = 1;

void
get_ip(char *name, struct sockaddr_in *addr)
{
    struct hostent *h;

    h = gethostbyname(name);
    printf("getting address of %s.\n", name);
    if (h) {
	addr->sin_len = sizeof (*addr);
	addr->sin_family = AF_INET;
	memcpy(&addr->sin_addr.s_addr, h->h_addr_list[0], h->h_length);

	return;
    }
    fprintf(stderr, "bad host: %s. ", name);
    herror("gethostbyname: ");
    exit(1);
}

int
prototosocktype(char *proto)
{
    if (strcmp(proto, "tcp") == 0)
	return SOCK_STREAM;
    if (strcmp(proto, "udp") == 0)
	return SOCK_DGRAM;
    return -1;
}

void
make_socket(struct sockaddr_in host, char *proto, char *port)
{
    int sock;
    struct servent *se;

    sock = socket(AF_INET, prototosocktype(proto), 0);
    if (sock == -1) {
	perror("socket");
	return;
    }

    setsockopt(0, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one));

    if (isdigit(port[0])) {
	host.sin_port = htons(atoi(port));
    } else {
	se = getservbyname(port, proto);
	if (se == NULL) {
	    fprintf(stderr, "bad service: %s. ", port);
	    herror("getservbyname: ");
	    return;
	}
	host.sin_port = se->s_port;
    }

    if (bind(sock, (struct sockaddr *)&host, sizeof(host))) {
    printf("binding to port %d host %08lx\n", ntohs(host.sin_port), ntohl(host.sin_addr.s_addr));
	perror("bind");
	return;
    }

    if (listen(sock, 1) == -1) {
	perror("listen");
    }

    printf("listening on port %d\n", ntohs(host.sin_port));
}

int
main(int argc, char **argv)
{
    if (argc >= 2) {
	struct sockaddr_in hostaddr;
	char *proto = "tcp";
	int ac;

	get_ip(argv[1], &hostaddr);

	for (ac = 2; ac < argc; ac++) {
	    if (prototosocktype(argv[ac]) != -1) {
		proto = argv[ac];
		continue;
	    }
	    make_socket(hostaddr, proto, argv[ac]);
	}

	/* and do nothing else anymore */
	select(0, NULL, NULL, NULL, NULL);
    }
}

-Olaf.
--
___ Olaf 'Rhialto' Seibert      D787B44DFC896063 4CBB95A5BD1DAA96 
\X/ There are no lemurs in this post    rhialto@polder.ubc.kun.nl