Annotation of libwww/Library/src/HTTCP.c, revision 2.10
1.1 timbl 1: /* Generic Communication Code HTTCP.c
2: ** ==========================
3: **
4: ** This code is in common between client and server sides.
5: **
6: ** 16 Jan 92 TBL Fix strtol() undefined on CMU Mach.
7: ** 25 Jun 92 JFG Added DECNET option through TCP socket emulation.
2.7 duns 8: ** 13 Sep 93 MD Added correct return of vmserrorno for HTInetStatus.
9: ** Added decoding of vms error message for MULTINET.
1.1 timbl 10: */
11:
12:
13: #include "HTUtils.h"
14: #include "tcp.h" /* Defines SHORT_NAMES if necessary */
15: #ifdef SHORT_NAMES
16: #define HTInetStatus HTInStat
17: #define HTInetString HTInStri
18: #define HTParseInet HTPaInet
19: #endif
20:
2.8 luotonen 21:
1.1 timbl 22: /* Module-Wide variables
23: */
24:
25: PRIVATE char *hostname=0; /* The name of this host */
26:
27:
28: /* PUBLIC VARIABLES
29: */
30:
31: /* PUBLIC SockA HTHostAddress; */ /* The internet address of the host */
32: /* Valid after call to HTHostName() */
33:
34: /* Encode INET status (as in sys/errno.h) inet_status()
35: ** ------------------
36: **
37: ** On entry,
38: ** where gives a description of what caused the error
39: ** global errno gives the error number in the unix way.
40: **
41: ** On return,
42: ** returns a negative status in the unix way.
43: */
44: #ifndef PCNFS
2.7 duns 45: #ifdef VMS
2.10 ! duns 46: #ifndef __DECC
1.1 timbl 47: extern int uerrno; /* Deposit of error info (as per errno.h) */
2.7 duns 48: extern volatile noshare int socket_errno; /* socket VMS error info
49: (used for translation of vmserrno) */
1.1 timbl 50: extern volatile noshare int vmserrno; /* Deposit of VMS error info */
51: extern volatile noshare int errno; /* noshare to avoid PSECT conflict */
2.10 ! duns 52: #endif /* not DECC */
2.7 duns 53: #else /* VMS */
1.1 timbl 54: #ifndef errno
55: extern int errno;
56: #endif /* errno */
2.7 duns 57: #endif /* VMS */
1.1 timbl 58:
59: #ifndef VM
2.7 duns 60: #ifndef VMS
1.1 timbl 61: #ifndef NeXT
62: #ifndef THINK_C
63: extern char *sys_errlist[]; /* see man perror on cernvax */
64: extern int sys_nerr;
65: #endif /* think c */
66: #endif /* NeXT */
2.7 duns 67: #endif /* VMS */
1.1 timbl 68: #endif /* VM */
69:
70: #endif /* PCNFS */
71:
72: /* Report Internet Error
73: ** ---------------------
74: */
75: #ifdef __STDC__
76: PUBLIC int HTInetStatus(char *where)
77: #else
78: PUBLIC int HTInetStatus(where)
79: char *where;
80: #endif
81: {
2.7 duns 82: #ifdef VMS
83: #ifdef MULTINET
84: socket_errno = vmserrno;
85: #endif
86: #endif
87:
2.9 luotonen 88: CTRACE(tfp, "TCP......... Error %d in `errno' after call to %s() failed.\n\t%s\n",
1.1 timbl 89: errno, where,
2.7 duns 90:
1.1 timbl 91: #ifdef VM
92: "(Error number not translated)"); /* What Is the VM equiv? */
93: #define ER_NO_TRANS_DONE
94: #endif
2.7 duns 95: #ifdef VMS
96: #ifdef MULTINET
97: vms_errno_string());
98: #else
1.1 timbl 99: "(Error number not translated)");
2.7 duns 100: #endif
1.1 timbl 101: #define ER_NO_TRANS_DONE
102: #endif
103: #ifdef NeXT
104: strerror(errno));
105: #define ER_NO_TRANS_DONE
106: #endif
107: #ifdef THINK_C
108: strerror(errno));
109: #define ER_NO_TRANS_DONE
110: #endif
111:
112: #ifndef ER_NO_TRANS_DONE
113: errno < sys_nerr ? sys_errlist[errno] : "Unknown error" );
114: #endif
115:
2.7 duns 116: #ifdef VMS
117: #ifndef MULTINET
1.1 timbl 118: CTRACE(tfp, " Unix error number (uerrno) = %ld dec\n", uerrno);
119: CTRACE(tfp, " VMS error (vmserrno) = %lx hex\n", vmserrno);
120: #endif
2.7 duns 121: #endif
122:
123: #ifdef VMS
124: /* uerrno and errno happen to be zero if vmserrno <> 0 */
125: return -vmserrno;
126: #else
1.1 timbl 127: return -errno;
2.7 duns 128: #endif
1.1 timbl 129: }
130:
131:
132: /* Parse a cardinal value parse_cardinal()
133: ** ----------------------
134: **
135: ** On entry,
136: ** *pp points to first character to be interpreted, terminated by
137: ** non 0:9 character.
138: ** *pstatus points to status already valid
139: ** maxvalue gives the largest allowable value.
140: **
141: ** On exit,
142: ** *pp points to first unread character
143: ** *pstatus points to status updated iff bad
144: */
145:
146: PUBLIC unsigned int HTCardinal ARGS3
147: (int *, pstatus,
148: char **, pp,
149: unsigned int, max_value)
150: {
151: int n;
152: if ( (**pp<'0') || (**pp>'9')) { /* Null string is error */
153: *pstatus = -3; /* No number where one expeceted */
154: return 0;
155: }
156:
157: n=0;
158: while ((**pp>='0') && (**pp<='9')) n = n*10 + *((*pp)++) - '0';
159:
160: if (n>max_value) {
161: *pstatus = -4; /* Cardinal outside range */
162: return 0;
163: }
164:
165: return n;
166: }
167:
168:
169: #ifndef DECNET /* Function only used below for a trace message */
170:
171: /* Produce a string for an Internet address
172: ** ----------------------------------------
173: **
174: ** On exit,
175: ** returns a pointer to a static string which must be copied if
176: ** it is to be kept.
177: */
178:
179: PUBLIC CONST char * HTInetString ARGS1(SockA*,sin)
180: {
181: static char string[16];
182: sprintf(string, "%d.%d.%d.%d",
183: (int)*((unsigned char *)(&sin->sin_addr)+0),
184: (int)*((unsigned char *)(&sin->sin_addr)+1),
185: (int)*((unsigned char *)(&sin->sin_addr)+2),
186: (int)*((unsigned char *)(&sin->sin_addr)+3));
187: return string;
188: }
189: #endif /* Decnet */
190:
191:
192: /* Parse a network node address and port
193: ** -------------------------------------
194: **
195: ** On entry,
196: ** str points to a string with a node name or number,
197: ** with optional trailing colon and port number.
198: ** sin points to the binary internet or decnet address field.
199: **
200: ** On exit,
201: ** *sin is filled in. If no port is specified in str, that
202: ** field is left unchanged in *sin.
203: */
204: PUBLIC int HTParseInet ARGS2(SockA *,sin, CONST char *,str)
205: {
206: char *port;
207: char host[256];
208: struct hostent *phost; /* Pointer to host - See netdb.h */
209: strcpy(host, str); /* Take a copy we can mutilate */
210:
211:
212:
213: /* Parse port number if present
214: */
2.8 luotonen 215: if ((port=strchr(host, ':'))) {
1.1 timbl 216: *port++ = 0; /* Chop off port */
217: if (port[0]>='0' && port[0]<='9') {
218:
219: #ifdef unix
220: sin->sin_port = htons(atol(port));
221: #else /* VMS */
222: #ifdef DECNET
223: sin->sdn_objnum = (unsigned char) (strtol(port, (char**)0 , 10));
224: #else
225: sin->sin_port = htons(strtol(port, (char**)0 , 10));
226: #endif /* Decnet */
227: #endif /* Unix vs. VMS */
228:
229: } else {
230:
231: #ifdef SUPPRESS /* 1. crashes!?!. 2. Not recommended */
232: struct servent * serv = getservbyname(port, (char*)0);
233: if (serv) sin->sin_port = serv->s_port;
2.9 luotonen 234: else if (TRACE) fprintf(stderr, "TCP......... Unknown service %s\n", port);
1.1 timbl 235: #endif
236: }
237: }
238:
239: #ifdef DECNET
240: /* read Decnet node name. @@ Should know about DECnet addresses, but it's
241: probably worth waiting until the Phase transition from IV to V. */
242:
243: sin->sdn_nam.n_len = min(DN_MAXNAML, strlen(host)); /* <=6 in phase 4 */
244: strncpy (sin->sdn_nam.n_name, host, sin->sdn_nam.n_len + 1);
245:
246: if (TRACE) fprintf(stderr,
247: "DECnet: Parsed address as object number %d on host %.6s...\n",
248: sin->sdn_objnum, host);
249:
250: #else /* parse Internet host */
251:
252: /* Parse host number if present.
253: */
254: if (*host>='0' && *host<='9') { /* Numeric node address: */
255: sin->sin_addr.s_addr = inet_addr(host); /* See arpa/inet.h */
256:
257: } else { /* Alphanumeric node name: */
258: #ifdef MVS /* Oustanding problem with crash in MVS gethostbyname */
2.6 timbl 259: if(TRACE)fprintf(stderr, "HTTCP: Calling gethostbyname(%s)\n", host);
1.1 timbl 260: #endif
261: phost=gethostbyname(host); /* See netdb.h */
262: #ifdef MVS
2.6 timbl 263: if(TRACE)fprintf(stderr, "HTTCP: gethostbyname() returned %d\n", phost);
1.1 timbl 264: #endif
265: if (!phost) {
266: if (TRACE) fprintf(stderr,
267: "HTTPAccess: Can't find internet node name `%s'.\n",host);
268: return -1; /* Fail? */
269: }
270: memcpy(&sin->sin_addr, phost->h_addr, phost->h_length);
271: }
272:
273: if (TRACE) fprintf(stderr,
2.9 luotonen 274: "TCP......... Parsed address as port %d, IP address %d.%d.%d.%d\n",
2.5 timbl 275: (int)ntohs(sin->sin_port),
1.1 timbl 276: (int)*((unsigned char *)(&sin->sin_addr)+0),
277: (int)*((unsigned char *)(&sin->sin_addr)+1),
278: (int)*((unsigned char *)(&sin->sin_addr)+2),
279: (int)*((unsigned char *)(&sin->sin_addr)+3));
280:
281: #endif /* Internet vs. Decnet */
282:
283: return 0; /* OK */
284: }
285:
286:
2.8 luotonen 287: /*
288: ** Get host name of the machine on the other end of a socket.
289: */
290: PUBLIC char * HTGetHostName ARGS1(int, soc)
291: {
292: struct sockaddr addr;
293: int len = sizeof(struct sockaddr);
294: struct in_addr *iaddr;
295: struct hostent * phost; /* Pointer to host -- See netdb.h */
296: char *name = NULL;
297:
298: #ifdef DECNET /* Decnet ain't got no damn name server 8#OO */
299: return NULL;
300: #else
301: if (getpeername(soc, &addr, &len) < 0)
302: return NULL;
303:
304: iaddr = &(((struct sockaddr_in *)&addr)->sin_addr);
305: phost=gethostbyaddr((char*)iaddr,
306: sizeof(struct in_addr),
307: AF_INET);
308: if (!phost) {
309: if (TRACE) fprintf(stderr,
2.9 luotonen 310: "TCP......... Can't find internet node name for peer!!\n");
2.8 luotonen 311: return NULL;
312: }
313: StrAllocCopy(name, phost->h_name);
2.9 luotonen 314: if (TRACE) fprintf(stderr, "TCP......... Peer name is `%s'\n", name);
2.8 luotonen 315:
316: return name;
317:
318: #endif /* not DECNET */
319: }
320:
321:
1.1 timbl 322: /* Derive the name of the host on which we are
323: ** -------------------------------------------
324: **
325: */
2.8 luotonen 326: PRIVATE void get_host_details NOARGS
1.1 timbl 327:
328: #ifndef MAXHOSTNAMELEN
329: #define MAXHOSTNAMELEN 64 /* Arbitrary limit */
330: #endif
331:
332: {
333: char name[MAXHOSTNAMELEN+1]; /* The name of this host */
334: struct hostent * phost; /* Pointer to host -- See netdb.h */
335: int namelength = sizeof(name);
336:
337: if (hostname) return; /* Already done */
338: gethostname(name, namelength); /* Without domain */
2.9 luotonen 339: CTRACE(tfp, "TCP......... Local host name is %s\n", name);
1.1 timbl 340: StrAllocCopy(hostname, name);
341:
342: #ifndef DECNET /* Decnet ain't got no damn name server 8#OO */
343: phost=gethostbyname(name); /* See netdb.h */
344: if (!phost) {
345: if (TRACE) fprintf(stderr,
2.9 luotonen 346: "TCP......... Can't find my own internet node address for `%s'!!\n",
1.1 timbl 347: name);
348: return; /* Fail! */
349: }
350: StrAllocCopy(hostname, phost->h_name);
2.9 luotonen 351: CTRACE(tfp, "TCP......... Full local host name is %s\n", hostname);
2.8 luotonen 352:
353: #ifdef NEED_HOST_ADDRESS /* no -- needs name server! */
1.1 timbl 354: memcpy(&HTHostAddress, &phost->h_addr, phost->h_length);
355: if (TRACE) fprintf(stderr, " Name server says that I am `%s' = %s\n",
356: hostname, HTInetString(&HTHostAddress));
2.8 luotonen 357: #endif /* NEED_HOST_ADDRESS */
1.1 timbl 358:
359: #endif /* not Decnet */
360: }
361:
362: #ifdef __STDC__
363: PUBLIC const char * HTHostName(void)
364: #else
365: PUBLIC char * HTHostName()
366: #endif
367: {
368: get_host_details();
369: return hostname;
370: }
371:
Webmaster