brad@bradley.bradley.edu (Bradley E. Smith) (05/29/91)
I am not sure why but the following program has problems..... HARDWARE USED: SUN 470 SunOS 4.1.1 - NO SUN SLC SunOS 4.1.1 - NO IBM RT BSD OS - YES AT&T 3B2 WIN TCP 3.2 - YES AT&T 386 WIN TCP 3.0 - YES What happens: As the program is listed below (make sure you change the host name if you are going to try it), 'bind(2)' fails on the suns with EADDRNOTAVAIL. The other machines work just fine. If I change/remove the x(), and the '{' '}' so that the whole program is in 1 function (ie I just delete a few lines everything is in main()). It works just fine. Any thoughts? #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <errno.h> #ifdef SYSV #include <sys/in.h> #include <sys/inet.h> #else #include <netinet/in.h> #include <arpa/inet.h> #endif #include <sys/param.h> #include <netdb.h> extern int errno; main() { x(); } x() { int sock2, length; struct sockaddr_in backupserver; struct hostent *hp; extern struct hostent *gethostbyname(); extern char *inet_ntoa(); int sockoptval; sockoptval = 1; hp = gethostbyname("bradley"); if(hp == NULL) { sock2 = errno * -1; return(sock2); /* unknown error */ } sock2 = socket(AF_INET, SOCK_STREAM, 0); if(sock2 < 0) { sock2 = errno * (-1); return(sock2); } if( setsockopt(sock2, SOL_SOCKET, SO_DEBUG, &sockoptval, sizeof(sockoptval))) perror("setsockopt"); if( setsockopt(sock2, SOL_SOCKET, SO_REUSEADDR, &sockoptval, sizeof(sockoptval))) perror("setsockopt"); backupserver.sin_family = AF_INET; bcopy((char *) hp->h_addr, (char *) &backupserver.sin_addr.s_addr, hp->h_length); backupserver.sin_port = htons(4321); length = sizeof(struct sockaddr_in); if(bind(sock2, (struct sockaddr *) &backupserver, length)) { perror("bind"); sock2 = errno * (-1); return(sock2); } length = sizeof(backupserver); if(getsockname(sock2, (struct sockaddr *)&backupserver, &length)) { sock2 = errno * (-1); return(sock2); } (void) printf("OK: Socket has port # %d\n", ntohs(backupserver.sin_port)); return(sock2); } -- Bradley Smith Network & Technical Services @ Bradley University, Peoria, IL brad@bradley.edu --- 309-677-2337
jik@athena.mit.edu (Jonathan I. Kamens) (05/30/91)
You need to bzero the sockaddr_in structure (backupserver) before putting anything into it. I compiled your program as-is (with a different host name) and it didn't work. I then added the line "bzero((char *) &backupserver, sizeof(backupserver));" right before "backupserver.sin_family = AF_INET;" and it worked fine. -- Jonathan Kamens USnail: MIT Project Athena 11 Ashford Terrace jik@Athena.MIT.EDU Allston, MA 02134 Office: 617-253-8085 Home: 617-782-0710
rd@zildjian.chorus.fr (Roland Dirlewanger) (05/30/91)
In article <1991May29.145535.23801@bradley.bradley.edu> brad@bradley.bradley.edu (Bradley E. Smith) writes: %% I am not sure why but the following program has problems..... %% %% HARDWARE USED: %% %% SUN 470 SunOS 4.1.1 - NO %% SUN SLC SunOS 4.1.1 - NO %% IBM RT BSD OS - YES %% AT&T 3B2 WIN TCP 3.2 - YES %% AT&T 386 WIN TCP 3.0 - YES %% %% What happens: As the program is listed below (make sure you change %% the host name if you are going to try it), 'bind(2)' fails on the %% suns with EADDRNOTAVAIL. The other machines work just fine. %% %% If I change/remove the x(), and the '{' '}' so that the whole %% program is in 1 function (ie I just delete a few lines everything %% is in main()). It works just fine. %% %% [Source program deleted] Implementations based on the BSD TCP/IP distribution (such as SunOS) check that the last eight bytes (the sin_zero field) of a sockaddr_in are set to 0. If not, they complain. What happens, is that your "struct sockaddr_in backupserver" is allocated in the stack, thus initialized to random data. In main(), it happens to be initialized to 0, in x() it's not. To fix your problem, you may either: - declare "struct sockaddr_in backupserver" to be a static variable (thus garantied to be zeroed): x () { ... static struct sockaddr_in backupserver; ... } - insert somewhere before the bind() the following line: bzero (backupserver.sin_zero, sizeof backupserver.sin_zero); Hope this helped. -- Roland Dirlewanger E-mail: rd@chorus.fr Chorus systemes Phone: +33 1 30 64 82 85 6, Avenue Gustave Eiffel Fax: +33 1 30 57 00 66 F-78182 St Quentin en Yvelines Cedex
mouse@thunder.mcrcim.mcgill.edu (der Mouse) (06/02/91)
In article <1991May29.145535.23801@bradley.bradley.edu>, brad@bradley.bradley.edu (Bradley E. Smith) writes: > I am not sure why but the following program has problems..... [program deleted - problem with bind()] > HARDWARE USED: > SUN 470 SunOS 4.1.1 - NO > SUN SLC SunOS 4.1.1 - NO > IBM RT BSD OS - YES > AT&T 3B2 WIN TCP 3.2 - YES > AT&T 386 WIN TCP 3.0 - YES What you need to do is zero the supposedly-unused area of the struct sockaddr_in before calling bind(). As far as I know SunOS is the only system that imposes this requirement, but the range of systems I have actually checked this on is fairly small - 4.3 BSD is the only one that I'm sure doesn't require it. Try doing a bzero((char *)&backupserver,sizeof(backupserver)) before storing anything into it. That generally does it for me. The reason calling x() changes things is that backupserver (which is an auto variable) is allocated at a slightly different place on the stack, so the unused portion contains different stack trash. The working way places it so the unused portion contains zeros. der Mouse old: mcgill-vision!mouse new: mouse@larry.mcrcim.mcgill.edu