Commit | Line | Data |
---|---|---|
d185cb11 | 1 | /* |
792e6158 | 2 | * Copyright (c) 1983, 1995 Eric P. Allman |
31de980b KB |
3 | * Copyright (c) 1988, 1993 |
4 | * The Regents of the University of California. All rights reserved. | |
710322bb | 5 | * |
417f7a11 | 6 | * %sccs.include.redist.c% |
710322bb | 7 | */ |
d185cb11 | 8 | |
d0432129 | 9 | #include <errno.h> |
97543758 | 10 | #include "sendmail.h" |
6b6d57eb | 11 | # include <sys/mx.h> |
ef34cbda | 12 | |
710322bb KB |
13 | #ifndef lint |
14 | #ifdef DAEMON | |
890d2773 | 15 | static char sccsid[] = "@(#)daemon.c 8.104 (Berkeley) %G% (with daemon mode)"; |
710322bb | 16 | #else |
890d2773 | 17 | static char sccsid[] = "@(#)daemon.c 8.104 (Berkeley) %G% (without daemon mode)"; |
710322bb KB |
18 | #endif |
19 | #endif /* not lint */ | |
20 | ||
21 | #ifdef DAEMON | |
17a67c62 | 22 | |
377054c1 | 23 | # include <arpa/inet.h> |
17a67c62 | 24 | |
efe7f723 | 25 | #if NAMED_BIND |
ab6ca5e5 EA |
26 | # include <resolv.h> |
27 | #endif | |
28 | ||
298b05de EA |
29 | #if IP_SRCROUTE |
30 | # include <netinet/in_systm.h> | |
31 | # include <netinet/ip.h> | |
32 | # include <netinet/ip_var.h> | |
33 | #endif | |
34 | ||
ef34cbda EA |
35 | /* |
36 | ** DAEMON.C -- routines to use when running as a daemon. | |
2a16bae3 EA |
37 | ** |
38 | ** This entire file is highly dependent on the 4.2 BSD | |
39 | ** interprocess communication primitives. No attempt has | |
40 | ** been made to make this file portable to Version 7, | |
41 | ** Version 6, MPX files, etc. If you should try such a | |
42 | ** thing yourself, I recommend chucking the entire file | |
43 | ** and starting from scratch. Basic semantics are: | |
44 | ** | |
45 | ** getrequests() | |
46 | ** Opens a port and initiates a connection. | |
47 | ** Returns in a child. Must set InChannel and | |
48 | ** OutChannel appropriately. | |
eb8af3ce EA |
49 | ** clrdaemon() |
50 | ** Close any open files associated with getting | |
51 | ** the connection; this is used when running the queue, | |
52 | ** etc., to avoid having extra file descriptors during | |
53 | ** the queue run and to avoid confusing the network | |
54 | ** code (if it cares). | |
8657d05f | 55 | ** makeconnection(host, port, outfile, infile, usesecureport) |
2a16bae3 EA |
56 | ** Make a connection to the named host on the given |
57 | ** port. Set *outfile and *infile to the files | |
58 | ** appropriate for communication. Returns zero on | |
59 | ** success, else an exit status describing the | |
60 | ** error. | |
713c523f | 61 | ** host_map_lookup(map, hbuf, avp, pstat) |
5a4c03c6 | 62 | ** Convert the entry in hbuf into a canonical form. |
ef34cbda | 63 | */ |
6b6d57eb EA |
64 | |
65 | static FILE *MailPort; /* port that mail comes in on */ | |
ef34cbda EA |
66 | \f/* |
67 | ** GETREQUESTS -- open mail IPC port and get requests. | |
68 | ** | |
69 | ** Parameters: | |
70 | ** none. | |
71 | ** | |
72 | ** Returns: | |
73 | ** none. | |
74 | ** | |
75 | ** Side Effects: | |
76 | ** Waits until some interesting activity occurs. When | |
77 | ** it does, a child is created to process it, and the | |
78 | ** parent waits for completion. Return from this | |
40d27fed EA |
79 | ** routine is always in the child. The file pointers |
80 | ** "InChannel" and "OutChannel" should be set to point | |
81 | ** to the communication channel. | |
ef34cbda EA |
82 | */ |
83 | ||
8829f52e EA |
84 | int DaemonSocket = -1; /* fd describing socket */ |
85 | SOCKADDR DaemonAddr; /* socket for incoming */ | |
278c561a | 86 | int ListenQueueSize = 10; /* size of listen queue */ |
118dcfcf EA |
87 | int TcpRcvBufferSize = 0; /* size of TCP receive buffer */ |
88 | int TcpSndBufferSize = 0; /* size of TCP send buffer */ | |
14a39063 | 89 | |
ea07b2d2 | 90 | void |
7f108496 | 91 | getrequests() |
14a39063 | 92 | { |
7e3417e6 | 93 | int t; |
a90a7c55 | 94 | bool refusingconnections = TRUE; |
654398d7 | 95 | FILE *pidf; |
54c90151 | 96 | int socksize; |
a40faef5 | 97 | #if XDEBUG |
6e48b8f0 EA |
98 | bool j_has_dot; |
99 | #endif | |
0df908a9 | 100 | extern void reapchild(); |
14a39063 EA |
101 | |
102 | /* | |
103 | ** Set up the address for the mailer. | |
104 | */ | |
105 | ||
8829f52e EA |
106 | if (DaemonAddr.sin.sin_family == 0) |
107 | DaemonAddr.sin.sin_family = AF_INET; | |
108 | if (DaemonAddr.sin.sin_addr.s_addr == 0) | |
109 | DaemonAddr.sin.sin_addr.s_addr = INADDR_ANY; | |
110 | if (DaemonAddr.sin.sin_port == 0) | |
7f108496 | 111 | { |
c075e44e EA |
112 | register struct servent *sp; |
113 | ||
8829f52e EA |
114 | sp = getservbyname("smtp", "tcp"); |
115 | if (sp == NULL) | |
116 | { | |
9964213c | 117 | syserr("554 service \"smtp\" unknown"); |
c075e44e | 118 | DaemonAddr.sin.sin_port = htons(25); |
8829f52e | 119 | } |
c075e44e EA |
120 | else |
121 | DaemonAddr.sin.sin_port = sp->s_port; | |
7f108496 | 122 | } |
14a39063 EA |
123 | |
124 | /* | |
125 | ** Try to actually open the connection. | |
126 | */ | |
127 | ||
9678c96d | 128 | if (tTd(15, 1)) |
8829f52e | 129 | printf("getrequests: port 0x%x\n", DaemonAddr.sin.sin_port); |
14a39063 | 130 | |
7f108496 | 131 | /* get a socket for the SMTP connection */ |
15b0addc | 132 | socksize = opendaemonsocket(TRUE); |
14a39063 | 133 | |
39270cfd | 134 | (void) setsignal(SIGCHLD, reapchild); |
199d34eb | 135 | |
654398d7 EA |
136 | /* write the pid to the log file for posterity */ |
137 | pidf = fopen(PidFile, "w"); | |
138 | if (pidf != NULL) | |
139 | { | |
353ccd78 EA |
140 | extern char *CommandLineArgs; |
141 | ||
142 | /* write the process id on line 1 */ | |
654398d7 | 143 | fprintf(pidf, "%d\n", getpid()); |
353ccd78 EA |
144 | |
145 | /* line 2 contains all command line flags */ | |
146 | fprintf(pidf, "%s\n", CommandLineArgs); | |
147 | ||
148 | /* flush and close */ | |
654398d7 EA |
149 | fclose(pidf); |
150 | } | |
151 | ||
a40faef5 | 152 | #if XDEBUG |
6e48b8f0 | 153 | { |
15c7b837 | 154 | char jbuf[MAXHOSTNAMELEN]; |
6e48b8f0 | 155 | |
832e8a27 | 156 | expand("\201j", jbuf, sizeof jbuf, CurEnv); |
15c7b837 | 157 | j_has_dot = strchr(jbuf, '.') != NULL; |
6e48b8f0 EA |
158 | } |
159 | #endif | |
654398d7 | 160 | |
7f108496 | 161 | if (tTd(15, 1)) |
eb8af3ce | 162 | printf("getrequests: %d\n", DaemonSocket); |
2a16bae3 | 163 | |
7f108496 EA |
164 | struct wh wbuf; |
165 | ||
166 | wbuf.index = index; | |
167 | wbuf.count = 0; | |
168 | wbuf.ccount = cnt; | |
169 | wbuf.data = buf; | |
170 | write(MailPort, &wbuf, sizeof wbuf); | |
14a39063 | 171 | } |
1ab402f2 EA |
172 | \f/* |
173 | ** MAKECONNECTION -- make a connection to an SMTP socket on another machine. | |
174 | ** | |
175 | ** Parameters: | |
176 | ** host -- the name of the host. | |
e2d7c32a | 177 | ** port -- the port number to connect to. |
2ae0e0ed EA |
178 | ** mci -- a pointer to the mail connection information |
179 | ** structure to be filled in. | |
8657d05f EA |
180 | ** usesecureport -- if set, use a low numbered (reserved) |
181 | ** port to provide some rudimentary authentication. | |
1ab402f2 EA |
182 | ** |
183 | ** Returns: | |
184 | ** An exit code telling whether the connection could be | |
185 | ** made and if not why not. | |
186 | ** | |
187 | ** Side Effects: | |
188 | ** none. | |
189 | */ | |
190 | ||
3341995c | 191 | SOCKADDR CurHostAddr; /* address of current host */ |
9b95d94a | 192 | |
f2e44ded | 193 | int |
2ae0e0ed | 194 | makeconnection(host, port, mci, usesecureport) |
1ab402f2 | 195 | char *host; |
f7eb07a3 | 196 | u_short port; |
f2e44ded | 197 | register MCI *mci; |
8657d05f | 198 | bool usesecureport; |
1ab402f2 | 199 | { |
ea07b2d2 EA |
200 | register int i = 0; |
201 | register int s; | |
9e881165 | 202 | register struct hostent *hp = (struct hostent *)NULL; |
3341995c | 203 | SOCKADDR addr; |
fa163d3c | 204 | int sav_errno; |
3341995c | 205 | int addrlen; |
8d7cd263 | 206 | bool firstconnect; |
efe7f723 | 207 | #if NAMED_BIND |
35af2f06 EA |
208 | extern int h_errno; |
209 | #endif | |
1ab402f2 EA |
210 | |
211 | /* | |
212 | ** Set up the address for the mailer. | |
b3e29341 | 213 | ** Accept "[a.b.c.d]" syntax for host name. |
1ab402f2 EA |
214 | */ |
215 | ||
efe7f723 | 216 | #if NAMED_BIND |
459e21be | 217 | h_errno = 0; |
35af2f06 | 218 | #endif |
459e21be | 219 | errno = 0; |
f66cc88e | 220 | bzero(&CurHostAddr, sizeof CurHostAddr); |
649a3283 | 221 | SmtpPhase = mci->mci_phase = "initial connection"; |
f53bb556 | 222 | CurHostName = host; |
459e21be | 223 | |
b3e29341 EA |
224 | if (host[0] == '[') |
225 | { | |
e56baaff | 226 | long hid; |
f3d8f6d6 | 227 | register char *p = strchr(host, ']'); |
b3e29341 | 228 | |
e56baaff | 229 | if (p != NULL) |
b3e29341 | 230 | { |
e56baaff | 231 | *p = '\0'; |
a40faef5 | 232 | #if NETINET |
e56baaff | 233 | hid = inet_addr(&host[1]); |
b120ff69 | 234 | if (hid == -1) |
69d3adf7 | 235 | #endif |
b120ff69 EA |
236 | { |
237 | /* try it as a host name (avoid MX lookup) */ | |
5b7a2dfe | 238 | hp = sm_gethostbyname(&host[1]); |
53d4f262 EA |
239 | if (hp == NULL && p[-1] == '.') |
240 | { | |
fe188caa | 241 | #if NAMED_BIND |
e65a357f EA |
242 | int oldopts = _res.options; |
243 | ||
244 | _res.options &= ~(RES_DEFNAMES|RES_DNSRCH); | |
245 | #endif | |
53d4f262 | 246 | p[-1] = '\0'; |
5b7a2dfe | 247 | hp = sm_gethostbyname(&host[1]); |
53d4f262 | 248 | p[-1] = '.'; |
fe188caa | 249 | #if NAMED_BIND |
e65a357f EA |
250 | _res.options = oldopts; |
251 | #endif | |
53d4f262 | 252 | } |
b120ff69 EA |
253 | *p = ']'; |
254 | goto gothostent; | |
255 | } | |
e56baaff | 256 | *p = ']'; |
b3e29341 | 257 | } |
b120ff69 | 258 | if (p == NULL) |
b3e29341 | 259 | { |
b6edea3d | 260 | usrerr("553 Invalid numeric domain spec \"%s\"", host); |
4e1c01f9 | 261 | mci->mci_status = "5.1.2"; |
b3e29341 EA |
262 | return (EX_NOHOST); |
263 | } | |
a40faef5 | 264 | #if NETINET |
69d3adf7 | 265 | addr.sin.sin_family = AF_INET; /*XXX*/ |
3356c77c | 266 | addr.sin.sin_addr.s_addr = hid; |
69d3adf7 | 267 | #endif |
b3e29341 | 268 | } |
7f108496 EA |
269 | else |
270 | { | |
53d4f262 EA |
271 | register char *p = &host[strlen(host) - 1]; |
272 | ||
5b7a2dfe | 273 | hp = sm_gethostbyname(host); |
53d4f262 EA |
274 | if (hp == NULL && *p == '.') |
275 | { | |
fe188caa | 276 | #if NAMED_BIND |
e65a357f EA |
277 | int oldopts = _res.options; |
278 | ||
279 | _res.options &= ~(RES_DEFNAMES|RES_DNSRCH); | |
280 | #endif | |
53d4f262 | 281 | *p = '\0'; |
5b7a2dfe | 282 | hp = sm_gethostbyname(host); |
53d4f262 | 283 | *p = '.'; |
fe188caa | 284 | #if NAMED_BIND |
e65a357f EA |
285 | _res.options = oldopts; |
286 | #endif | |
53d4f262 | 287 | } |
b120ff69 | 288 | gothostent: |
e56baaff | 289 | if (hp == NULL) |
459e21be | 290 | { |
efe7f723 | 291 | #if NAMED_BIND |
a542cc51 EA |
292 | /* check for name server timeouts */ |
293 | if (errno == ETIMEDOUT || h_errno == TRY_AGAIN || | |
294 | (errno == ECONNREFUSED && UseNameServer)) | |
295 | { | |
b5e36a3d | 296 | mci->mci_status = "4.4.3"; |
35af2f06 | 297 | return (EX_TEMPFAIL); |
a542cc51 | 298 | } |
35af2f06 | 299 | #endif |
7f108496 | 300 | return (EX_NOHOST); |
459e21be | 301 | } |
3356c77c EA |
302 | addr.sa.sa_family = hp->h_addrtype; |
303 | switch (hp->h_addrtype) | |
304 | { | |
a40faef5 | 305 | #if NETINET |
3356c77c | 306 | case AF_INET: |
3341995c | 307 | bcopy(hp->h_addr, |
3356c77c | 308 | &addr.sin.sin_addr, |
648eb46e | 309 | INADDRSZ); |
3356c77c EA |
310 | break; |
311 | #endif | |
312 | ||
313 | default: | |
3341995c | 314 | bcopy(hp->h_addr, |
3356c77c | 315 | addr.sa.sa_data, |
3341995c | 316 | hp->h_length); |
3356c77c EA |
317 | break; |
318 | } | |
9e881165 | 319 | i = 1; |
7f108496 EA |
320 | } |
321 | ||
322 | /* | |
323 | ** Determine the port number. | |
324 | */ | |
325 | ||
26b672df | 326 | if (port == 0) |
7f108496 EA |
327 | { |
328 | register struct servent *sp = getservbyname("smtp", "tcp"); | |
329 | ||
330 | if (sp == NULL) | |
331 | { | |
84d442cc EA |
332 | #ifdef LOG |
333 | if (LogLevel > 2) | |
334 | syslog(LOG_ERR, "makeconnection: service \"smtp\" unknown"); | |
335 | #endif | |
c075e44e | 336 | port = htons(25); |
7f108496 | 337 | } |
c075e44e EA |
338 | else |
339 | port = sp->s_port; | |
3341995c EA |
340 | } |
341 | ||
3356c77c | 342 | switch (addr.sa.sa_family) |
3341995c | 343 | { |
a40faef5 | 344 | #if NETINET |
3341995c | 345 | case AF_INET: |
3356c77c | 346 | addr.sin.sin_port = port; |
3341995c EA |
347 | addrlen = sizeof (struct sockaddr_in); |
348 | break; | |
69d3adf7 | 349 | #endif |
3341995c | 350 | |
a40faef5 | 351 | #if NETISO |
3341995c EA |
352 | case AF_ISO: |
353 | /* assume two byte transport selector */ | |
354 | bcopy((char *) &port, TSEL((struct sockaddr_iso *) &addr), 2); | |
355 | addrlen = sizeof (struct sockaddr_iso); | |
356 | break; | |
357 | #endif | |
358 | ||
359 | default: | |
3356c77c | 360 | syserr("Can't connect to address family %d", addr.sa.sa_family); |
3341995c | 361 | return (EX_NOHOST); |
7f108496 | 362 | } |
1ab402f2 EA |
363 | |
364 | /* | |
365 | ** Try to actually open the connection. | |
366 | */ | |
367 | ||
b4f81c5d EA |
368 | #ifdef XLA |
369 | /* if too many connections, don't bother trying */ | |
370 | if (!xla_noqueue_ok(host)) | |
371 | return EX_TEMPFAIL; | |
372 | #endif | |
373 | ||
8d7cd263 | 374 | firstconnect = TRUE; |
6feb509e | 375 | for (;;) |
8657d05f | 376 | { |
6feb509e | 377 | if (tTd(16, 1)) |
3341995c EA |
378 | printf("makeconnection (%s [%s])\n", |
379 | host, anynet_ntoa(&addr)); | |
8657d05f | 380 | |
83c07d72 EA |
381 | /* save for logging */ |
382 | CurHostAddr = addr; | |
383 | ||
6feb509e EA |
384 | if (usesecureport) |
385 | { | |
386 | int rport = IPPORT_RESERVED - 1; | |
387 | ||
388 | s = rresvport(&rport); | |
389 | } | |
390 | else | |
391 | { | |
392 | s = socket(AF_INET, SOCK_STREAM, 0); | |
393 | } | |
394 | if (s < 0) | |
395 | { | |
396 | sav_errno = errno; | |
890d2773 | 397 | syserr("makeconnection: cannot create socket"); |
6feb509e EA |
398 | goto failure; |
399 | } | |
1ab402f2 | 400 | |
118dcfcf EA |
401 | #ifdef SO_SNDBUF |
402 | if (TcpSndBufferSize > 0) | |
403 | { | |
404 | if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, | |
53335960 | 405 | (char *) &TcpSndBufferSize, |
118dcfcf EA |
406 | sizeof(TcpSndBufferSize)) < 0) |
407 | syserr("makeconnection: setsockopt(SO_SNDBUF)"); | |
408 | } | |
409 | #endif | |
410 | ||
6feb509e EA |
411 | if (tTd(16, 1)) |
412 | printf("makeconnection: fd=%d\n", s); | |
78c9dc29 | 413 | |
6feb509e EA |
414 | /* turn on network debugging? */ |
415 | if (tTd(16, 101)) | |
416 | { | |
417 | int on = 1; | |
2e7d8e3e | 418 | (void) setsockopt(s, SOL_SOCKET, SO_DEBUG, |
6feb509e EA |
419 | (char *)&on, sizeof on); |
420 | } | |
421 | if (CurEnv->e_xfp != NULL) | |
422 | (void) fflush(CurEnv->e_xfp); /* for debugging */ | |
423 | errno = 0; /* for debugging */ | |
3341995c | 424 | if (connect(s, (struct sockaddr *) &addr, addrlen) >= 0) |
6feb509e EA |
425 | break; |
426 | ||
8d7cd263 EA |
427 | /* if running demand-dialed connection, try again */ |
428 | if (DialDelay > 0 && firstconnect) | |
429 | { | |
430 | if (tTd(16, 1)) | |
431 | printf("Connect failed (%s); trying again...\n", | |
432 | errstring(sav_errno)); | |
433 | firstconnect = FALSE; | |
434 | sleep(DialDelay); | |
435 | continue; | |
436 | } | |
437 | ||
6feb509e | 438 | /* couldn't connect.... figure out why */ |
fa163d3c JB |
439 | sav_errno = errno; |
440 | (void) close(s); | |
ea07b2d2 | 441 | if (hp != NULL && hp->h_addr_list[i]) |
9e881165 | 442 | { |
6feb509e | 443 | if (tTd(16, 1)) |
3341995c EA |
444 | printf("Connect failed (%s); trying new address....\n", |
445 | errstring(sav_errno)); | |
3356c77c EA |
446 | switch (addr.sa.sa_family) |
447 | { | |
a40faef5 | 448 | #if NETINET |
3356c77c | 449 | case AF_INET: |
3341995c | 450 | bcopy(hp->h_addr_list[i++], |
3356c77c | 451 | &addr.sin.sin_addr, |
648eb46e | 452 | INADDRSZ); |
3356c77c EA |
453 | break; |
454 | #endif | |
455 | ||
456 | default: | |
3341995c | 457 | bcopy(hp->h_addr_list[i++], |
3356c77c | 458 | addr.sa.sa_data, |
8657d05f | 459 | hp->h_length); |
3356c77c EA |
460 | break; |
461 | } | |
6feb509e | 462 | continue; |
9e881165 JB |
463 | } |
464 | ||
1ab402f2 EA |
465 | /* failure, decide if temporary or not */ |
466 | failure: | |
46500bf5 EA |
467 | #ifdef XLA |
468 | xla_host_end(host); | |
469 | #endif | |
1eaa5615 EA |
470 | if (transienterror(sav_errno)) |
471 | return EX_TEMPFAIL; | |
1eaa5615 EA |
472 | else |
473 | { | |
1eaa5615 EA |
474 | message("%s", errstring(sav_errno)); |
475 | return (EX_UNAVAILABLE); | |
1ab402f2 EA |
476 | } |
477 | } | |
478 | ||
479 | /* connection ok, put it into canonical form */ | |
e9d81da2 EA |
480 | if ((mci->mci_out = fdopen(s, "w")) == NULL || |
481 | (s = dup(s)) < 0 || | |
35f14050 | 482 | (mci->mci_in = fdopen(s, "r")) == NULL) |
e9d81da2 EA |
483 | { |
484 | syserr("cannot open SMTP client channel, fd=%d", s); | |
485 | return EX_TEMPFAIL; | |
486 | } | |
1ab402f2 | 487 | |
1aaa7dec | 488 | return (EX_OK); |
1ab402f2 | 489 | } |
2ec2faaa EA |
490 | \f/* |
491 | ** MYHOSTNAME -- return the name of this host. | |
492 | ** | |
493 | ** Parameters: | |
494 | ** hostbuf -- a place to return the name of this host. | |
05894fc6 | 495 | ** size -- the size of hostbuf. |
2ec2faaa EA |
496 | ** |
497 | ** Returns: | |
498 | ** A list of aliases for this host. | |
499 | ** | |
500 | ** Side Effects: | |
377054c1 | 501 | ** Adds numeric codes to $=w. |
2ec2faaa EA |
502 | */ |
503 | ||
a8ec2376 | 504 | struct hostent * |
05894fc6 | 505 | myhostname(hostbuf, size) |
2ec2faaa | 506 | char hostbuf[]; |
05894fc6 | 507 | int size; |
2ec2faaa | 508 | { |
740d17b3 | 509 | register struct hostent *hp; |
a94b65bf EA |
510 | extern bool getcanonname(); |
511 | extern int h_errno; | |
2ec2faaa | 512 | |
17a67c62 EA |
513 | if (gethostname(hostbuf, size) < 0) |
514 | { | |
515 | (void) strcpy(hostbuf, "localhost"); | |
516 | } | |
5b7a2dfe | 517 | hp = sm_gethostbyname(hostbuf); |
7309c0a5 | 518 | if (hp == NULL) |
056f9f43 | 519 | return NULL; |
a94b65bf EA |
520 | if (strchr(hp->h_name, '.') != NULL || strchr(hostbuf, '.') == NULL) |
521 | { | |
522 | (void) strncpy(hostbuf, hp->h_name, size - 1); | |
523 | hostbuf[size - 1] = '\0'; | |
524 | } | |
e9870a62 | 525 | |
a94b65bf | 526 | /* |
106a69e9 EA |
527 | ** If there is still no dot in the name, try looking for a |
528 | ** dotted alias. | |
a94b65bf EA |
529 | */ |
530 | ||
73ceac90 | 531 | if (strchr(hostbuf, '.') == NULL) |
7309c0a5 | 532 | { |
106a69e9 EA |
533 | char **ha; |
534 | ||
535 | for (ha = hp->h_aliases; *ha != NULL; ha++) | |
73ceac90 | 536 | { |
106a69e9 EA |
537 | if (strchr(*ha, '.') != NULL) |
538 | { | |
539 | (void) strncpy(hostbuf, *ha, size - 1); | |
540 | hostbuf[size - 1] = '\0'; | |
541 | break; | |
542 | } | |
73ceac90 | 543 | } |
7309c0a5 | 544 | } |
106a69e9 EA |
545 | |
546 | /* | |
547 | ** If _still_ no dot, wait for a while and try again -- it is | |
548 | ** possible that some service is starting up. This can result | |
549 | ** in excessive delays if the system is badly configured, but | |
550 | ** there really isn't a way around that, particularly given that | |
551 | ** the config file hasn't been read at this point. | |
552 | ** All in all, a bit of a mess. | |
553 | */ | |
554 | ||
555 | if (strchr(hostbuf, '.') == NULL && | |
556 | !getcanonname(hostbuf, size, TRUE)) | |
557 | { | |
558 | message("My unqualifed host name (%s) unknown; sleeping for retry", | |
559 | hostbuf); | |
560 | sleep(60); | |
561 | (void) getcanonname(hostbuf, size, TRUE); | |
562 | } | |
a8ec2376 | 563 | return (hp); |
2ec2faaa | 564 | } |
bbfde42f | 565 | \f/* |
3f03d7a7 EA |
566 | ** GETAUTHINFO -- get the real host name asociated with a file descriptor |
567 | ** | |
568 | ** Uses RFC1413 protocol to try to get info from the other end. | |
5973222c EA |
569 | ** |
570 | ** Parameters: | |
571 | ** fd -- the descriptor | |
572 | ** | |
573 | ** Returns: | |
3f03d7a7 | 574 | ** The user@host information associated with this descriptor. |
5973222c EA |
575 | */ |
576 | ||
3f03d7a7 EA |
577 | static jmp_buf CtxAuthTimeout; |
578 | ||
ea07b2d2 | 579 | static void |
3f03d7a7 EA |
580 | authtimeout() |
581 | { | |
582 | longjmp(CtxAuthTimeout, 1); | |
583 | } | |
584 | ||
5973222c | 585 | char * |
3f03d7a7 | 586 | getauthinfo(fd) |
5973222c EA |
587 | int fd; |
588 | { | |
3f03d7a7 | 589 | int falen; |
72bc63d1 | 590 | register char *p; |
3f03d7a7 EA |
591 | SOCKADDR la; |
592 | int lalen; | |
593 | register struct servent *sp; | |
594 | int s; | |
595 | int i; | |
3f03d7a7 | 596 | EVENT *ev; |
569e2784 | 597 | int nleft; |
6f74842a | 598 | char ibuf[MAXNAME + 1]; |
8b2f7f25 | 599 | char ibuf[MAXNAME + 1]; |
3f03d7a7 EA |
600 | static char hbuf[MAXNAME * 2 + 2]; |
601 | extern char *hostnamebyanyaddr(); | |
3f03d7a7 | 602 | |
07385570 | 603 | falen = sizeof RealHostAddr; |
703f8e63 EA |
604 | if (isatty(fd) || getpeername(fd, &RealHostAddr.sa, &falen) < 0 || |
605 | falen <= 0 || RealHostAddr.sa.sa_family == 0) | |
3f03d7a7 | 606 | { |
3f03d7a7 | 607 | (void) sprintf(hbuf, "%s@localhost", RealUserName); |
a9bac7a9 | 608 | if (tTd(9, 1)) |
3f03d7a7 EA |
609 | printf("getauthinfo: %s\n", hbuf); |
610 | return hbuf; | |
611 | } | |
612 | ||
07385570 EA |
613 | if (RealHostName == NULL) |
614 | { | |
615 | /* translate that to a host name */ | |
616 | RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr)); | |
617 | } | |
618 | ||
423d92e1 EA |
619 | if (TimeOuts.to_ident == 0) |
620 | goto noident; | |
621 | ||
3f03d7a7 | 622 | lalen = sizeof la; |
07385570 | 623 | if (RealHostAddr.sa.sa_family != AF_INET || |
3f03d7a7 EA |
624 | getsockname(fd, &la.sa, &lalen) < 0 || lalen <= 0 || |
625 | la.sa.sa_family != AF_INET) | |
626 | { | |
627 | /* no ident info */ | |
628 | goto noident; | |
629 | } | |
630 | ||
631 | /* create ident query */ | |
968f1a79 | 632 | (void) sprintf(ibuf, "%d,%d\r\n", |
07385570 | 633 | ntohs(RealHostAddr.sin.sin_port), ntohs(la.sin.sin_port)); |
3f03d7a7 EA |
634 | |
635 | /* create local address */ | |
c32e1955 | 636 | la.sin.sin_port = 0; |
3f03d7a7 EA |
637 | |
638 | /* create foreign address */ | |
639 | sp = getservbyname("auth", "tcp"); | |
640 | if (sp != NULL) | |
07385570 | 641 | RealHostAddr.sin.sin_port = sp->s_port; |
5973222c | 642 | else |
07385570 | 643 | RealHostAddr.sin.sin_port = htons(113); |
3f03d7a7 EA |
644 | |
645 | s = -1; | |
646 | if (setjmp(CtxAuthTimeout) != 0) | |
647 | { | |
648 | if (s >= 0) | |
649 | (void) close(s); | |
650 | goto noident; | |
651 | } | |
652 | ||
653 | /* put a timeout around the whole thing */ | |
cf7a936d | 654 | ev = setevent(TimeOuts.to_ident, authtimeout, 0); |
3f03d7a7 | 655 | |
c32e1955 | 656 | /* connect to foreign IDENT server using same address as SMTP socket */ |
3f03d7a7 EA |
657 | s = socket(AF_INET, SOCK_STREAM, 0); |
658 | if (s < 0) | |
659 | { | |
660 | clrevent(ev); | |
661 | goto noident; | |
662 | } | |
c32e1955 | 663 | if (bind(s, &la.sa, sizeof la.sin) < 0 || |
07385570 | 664 | connect(s, &RealHostAddr.sa, sizeof RealHostAddr.sin) < 0) |
3f03d7a7 | 665 | { |
57c59cf7 | 666 | goto closeident; |
3f03d7a7 EA |
667 | } |
668 | ||
a9bac7a9 | 669 | if (tTd(9, 10)) |
968f1a79 | 670 | printf("getauthinfo: sent %s", ibuf); |
3f03d7a7 EA |
671 | |
672 | /* send query */ | |
968f1a79 | 673 | if (write(s, ibuf, strlen(ibuf)) < 0) |
3f03d7a7 EA |
674 | goto closeident; |
675 | ||
676 | /* get result */ | |
968f1a79 | 677 | p = &ibuf[0]; |
5f219189 | 678 | nleft = sizeof ibuf - 1; |
569e2784 EA |
679 | while ((i = read(s, p, nleft)) > 0) |
680 | { | |
681 | p += i; | |
682 | nleft -= i; | |
683 | } | |
3f03d7a7 EA |
684 | (void) close(s); |
685 | clrevent(ev); | |
968f1a79 | 686 | if (i < 0 || p == &ibuf[0]) |
3f03d7a7 | 687 | goto noident; |
569e2784 EA |
688 | |
689 | if (*--p == '\n' && *--p == '\r') | |
690 | p--; | |
691 | *++p = '\0'; | |
3f03d7a7 | 692 | |
a9bac7a9 | 693 | if (tTd(9, 3)) |
968f1a79 | 694 | printf("getauthinfo: got %s\n", ibuf); |
3f03d7a7 EA |
695 | |
696 | /* parse result */ | |
968f1a79 | 697 | p = strchr(ibuf, ':'); |
3f03d7a7 EA |
698 | if (p == NULL) |
699 | { | |
700 | /* malformed response */ | |
701 | goto noident; | |
702 | } | |
703 | while (isascii(*++p) && isspace(*p)) | |
704 | continue; | |
705 | if (strncasecmp(p, "userid", 6) != 0) | |
706 | { | |
707 | /* presumably an error string */ | |
708 | goto noident; | |
709 | } | |
710 | p += 6; | |
711 | while (isascii(*p) && isspace(*p)) | |
712 | p++; | |
713 | if (*p++ != ':') | |
714 | { | |
715 | /* either useridxx or malformed response */ | |
716 | goto noident; | |
717 | } | |
718 | ||
719 | /* p now points to the OSTYPE field */ | |
146c5cc1 EA |
720 | while (isascii(*p) && isspace(*p)) |
721 | p++; | |
722 | if (strncasecmp(p, "other", 5) == 0 && | |
723 | (p[5] == ':' || p[5] == ' ' || p[5] == ',' || p[5] == '\0')) | |
724 | { | |
725 | /* not useful information */ | |
726 | goto noident; | |
727 | } | |
3f03d7a7 EA |
728 | p = strchr(p, ':'); |
729 | if (p == NULL) | |
730 | { | |
731 | /* malformed response */ | |
732 | goto noident; | |
733 | } | |
a9bac7a9 EA |
734 | |
735 | /* 1413 says don't do this -- but it's broken otherwise */ | |
736 | while (isascii(*++p) && isspace(*p)) | |
737 | continue; | |
3f03d7a7 | 738 | |
3fd289f3 | 739 | /* p now points to the authenticated name -- copy carefully */ |
68359be4 EA |
740 | cleanstrcpy(hbuf, p, MAXNAME); |
741 | i = strlen(hbuf); | |
3fd289f3 EA |
742 | hbuf[i++] = '@'; |
743 | strcpy(&hbuf[i], RealHostName == NULL ? "localhost" : RealHostName); | |
298b05de | 744 | goto postident; |
a9bac7a9 | 745 | |
57c59cf7 EA |
746 | closeident: |
747 | (void) close(s); | |
748 | clrevent(ev); | |
749 | ||
a9bac7a9 | 750 | noident: |
389c0d5e EA |
751 | if (RealHostName == NULL) |
752 | { | |
753 | if (tTd(9, 1)) | |
754 | printf("getauthinfo: NULL\n"); | |
755 | return NULL; | |
756 | } | |
a9bac7a9 EA |
757 | (void) strcpy(hbuf, RealHostName); |
758 | ||
298b05de EA |
759 | postident: |
760 | #if IP_SRCROUTE | |
761 | /* | |
762 | ** Extract IP source routing information. | |
763 | ** | |
764 | ** Format of output for a connection from site a through b | |
765 | ** through c to d: | |
766 | ** loose: @site-c@site-b:site-a | |
767 | ** strict: !@site-c@site-b:site-a | |
768 | ** | |
769 | ** o - pointer within ipopt_list structure. | |
770 | ** q - pointer within ls/ss rr route data | |
771 | ** p - pointer to hbuf | |
772 | */ | |
773 | ||
774 | if (RealHostAddr.sa.sa_family == AF_INET) | |
775 | { | |
776 | int ipoptlen, j; | |
83d195af | 777 | u_char *q; |
298b05de EA |
778 | u_char *o; |
779 | struct in_addr addr; | |
780 | struct ipoption ipopt; | |
781 | ||
782 | ipoptlen = sizeof ipopt; | |
783 | if (getsockopt(fd, IPPROTO_IP, IP_OPTIONS, | |
784 | (char *) &ipopt, &ipoptlen) < 0) | |
785 | goto noipsr; | |
786 | if (ipoptlen == 0) | |
787 | goto noipsr; | |
83d195af | 788 | o = (u_char *) ipopt.ipopt_list; |
d96532ac | 789 | while (o != NULL && o < (u_char *) &ipopt + ipoptlen) |
298b05de EA |
790 | { |
791 | switch (*o) | |
792 | { | |
793 | case IPOPT_EOL: | |
794 | o = NULL; | |
795 | break; | |
796 | ||
797 | case IPOPT_NOP: | |
798 | o++; | |
799 | break; | |
800 | ||
801 | case IPOPT_SSRR: | |
802 | case IPOPT_LSRR: | |
803 | p = &hbuf[strlen(hbuf)]; | |
804 | sprintf(p, " [%s@%s", | |
805 | *o == IPOPT_SSRR ? "!" : "", | |
806 | inet_ntoa(ipopt.ipopt_dst)); | |
807 | p += strlen(p); | |
808 | ||
809 | /* o[1] is option length */ | |
810 | j = *++o / sizeof(struct in_addr) - 1; | |
811 | ||
812 | /* q skips length and router pointer to data */ | |
813 | q = o + 2; | |
814 | for ( ; j >= 0; j--) | |
815 | { | |
816 | memcpy(&addr, q, sizeof(addr)); | |
83d195af | 817 | sprintf(p, "%c%s", |
298b05de EA |
818 | j ? '@' : ':', |
819 | inet_ntoa(addr)); | |
83d195af EA |
820 | p += strlen(p); |
821 | q += sizeof(struct in_addr); | |
298b05de EA |
822 | } |
823 | o += *o; | |
824 | break; | |
825 | ||
826 | default: | |
827 | /* Skip over option */ | |
828 | o += o[1]; | |
829 | break; | |
830 | } | |
831 | } | |
832 | strcat(hbuf,"]"); | |
833 | goto postipsr; | |
834 | } | |
835 | #endif | |
836 | ||
837 | noipsr: | |
389c0d5e | 838 | if (RealHostName != NULL && RealHostName[0] != '[') |
3f03d7a7 EA |
839 | { |
840 | p = &hbuf[strlen(hbuf)]; | |
841 | (void) sprintf(p, " [%s]", anynet_ntoa(&RealHostAddr)); | |
842 | } | |
298b05de EA |
843 | |
844 | postipsr: | |
a9bac7a9 | 845 | if (tTd(9, 1)) |
3f03d7a7 | 846 | printf("getauthinfo: %s\n", hbuf); |
5973222c EA |
847 | return hbuf; |
848 | } | |
849 | \f/* | |
713c523f | 850 | ** HOST_MAP_LOOKUP -- turn a hostname into canonical form |
42fa5d67 EA |
851 | ** |
852 | ** Parameters: | |
5a4c03c6 | 853 | ** map -- a pointer to this map (unused). |
713c523f | 854 | ** name -- the (presumably unqualified) hostname. |
3ff91010 | 855 | ** av -- unused -- for compatibility with other mapping |
0cf5a7ba | 856 | ** functions. |
d1db7a89 EA |
857 | ** statp -- an exit status (out parameter) -- set to |
858 | ** EX_TEMPFAIL if the name server is unavailable. | |
42fa5d67 EA |
859 | ** |
860 | ** Returns: | |
861 | ** The mapping, if found. | |
862 | ** NULL if no mapping found. | |
863 | ** | |
864 | ** Side Effects: | |
865 | ** Looks up the host specified in hbuf. If it is not | |
866 | ** the canonical name for that host, return the canonical | |
867 | ** name. | |
868 | */ | |
bbfde42f | 869 | |
42fa5d67 | 870 | char * |
3ff91010 | 871 | host_map_lookup(map, name, av, statp) |
5a4c03c6 | 872 | MAP *map; |
713c523f | 873 | char *name; |
3ff91010 | 874 | char **av; |
d1db7a89 | 875 | int *statp; |
217a0102 EA |
876 | { |
877 | register struct hostent *hp; | |
d2dc4dd0 | 878 | struct in_addr in_addr; |
5a4c03c6 | 879 | char *cp; |
b97dd58b | 880 | register STAB *s; |
8446c922 | 881 | char hbuf[MAXNAME + 1]; |
efe7f723 | 882 | #if NAMED_BIND |
b97dd58b | 883 | extern int h_errno; |
68d8d275 | 884 | #endif |
217a0102 | 885 | |
33e4da31 | 886 | /* |
b97dd58b EA |
887 | ** See if we have already looked up this name. If so, just |
888 | ** return it. | |
889 | */ | |
890 | ||
713c523f | 891 | s = stab(name, ST_NAMECANON, ST_ENTER); |
b97dd58b EA |
892 | if (bitset(NCF_VALID, s->s_namecanon.nc_flags)) |
893 | { | |
d3b6a883 | 894 | if (tTd(9, 1)) |
713c523f | 895 | printf("host_map_lookup(%s) => CACHE %s\n", |
c5fa3645 EA |
896 | name, |
897 | s->s_namecanon.nc_cname == NULL | |
898 | ? "NULL" | |
6d3d9b76 | 899 | : s->s_namecanon.nc_cname); |
b97dd58b | 900 | errno = s->s_namecanon.nc_errno; |
efe7f723 | 901 | #if NAMED_BIND |
b97dd58b | 902 | h_errno = s->s_namecanon.nc_herrno; |
68d8d275 | 903 | #endif |
b97dd58b | 904 | *statp = s->s_namecanon.nc_stat; |
f435e9f3 | 905 | if (*statp == EX_TEMPFAIL) |
e1a4f0fb | 906 | { |
4e1c01f9 | 907 | CurEnv->e_status = "4.4.3"; |
f435e9f3 | 908 | usrerr("451 %s: Name server timeout", |
e1a4f0fb | 909 | shortenstring(name, 33)); |
e1a4f0fb | 910 | } |
b97dd58b EA |
911 | return s->s_namecanon.nc_cname; |
912 | } | |
913 | ||
914 | /* | |
915 | ** If first character is a bracket, then it is an address | |
916 | ** lookup. Address is copied into a temporary buffer to | |
713c523f | 917 | ** strip the brackets and to preserve name if address is |
b97dd58b EA |
918 | ** unknown. |
919 | */ | |
42fa5d67 | 920 | |
713c523f | 921 | if (*name != '[') |
42fa5d67 | 922 | { |
0cf5a7ba EA |
923 | extern bool getcanonname(); |
924 | ||
a97feb13 | 925 | if (tTd(9, 1)) |
713c523f | 926 | printf("host_map_lookup(%s) => ", name); |
b97dd58b | 927 | s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ |
8446c922 EA |
928 | if (strlen(name) < sizeof hbuf) |
929 | (void) strcpy(hbuf, name); | |
930 | else | |
931 | { | |
932 | bcopy(name, hbuf, sizeof hbuf - 1); | |
933 | hbuf[sizeof hbuf - 1] = '\0'; | |
934 | } | |
d9e4f92e | 935 | if (getcanonname(hbuf, sizeof hbuf - 1, !HasWildcardMX)) |
1d136a1f EA |
936 | { |
937 | if (tTd(9, 1)) | |
938 | printf("%s\n", hbuf); | |
3ff91010 EA |
939 | cp = map_rewrite(map, hbuf, strlen(hbuf), av); |
940 | s->s_namecanon.nc_cname = newstr(cp); | |
941 | return cp; | |
1d136a1f | 942 | } |
42fa5d67 | 943 | else |
1d136a1f | 944 | { |
d1db7a89 | 945 | register struct hostent *hp; |
d1db7a89 | 946 | |
b97dd58b | 947 | s->s_namecanon.nc_errno = errno; |
efe7f723 | 948 | #if NAMED_BIND |
b97dd58b | 949 | s->s_namecanon.nc_herrno = h_errno; |
68d8d275 EA |
950 | if (tTd(9, 1)) |
951 | printf("FAIL (%d)\n", h_errno); | |
d1db7a89 EA |
952 | switch (h_errno) |
953 | { | |
954 | case TRY_AGAIN: | |
c281eee3 | 955 | if (UseNameServer) |
7ffb494c | 956 | { |
4e1c01f9 | 957 | CurEnv->e_status = "4.4.3"; |
f435e9f3 | 958 | usrerr("451 %s: Name server timeout", |
e1a4f0fb | 959 | shortenstring(name, 33)); |
7ffb494c | 960 | } |
d1db7a89 EA |
961 | *statp = EX_TEMPFAIL; |
962 | break; | |
963 | ||
964 | case HOST_NOT_FOUND: | |
886bf7ce | 965 | case NO_DATA: |
d1db7a89 EA |
966 | *statp = EX_NOHOST; |
967 | break; | |
968 | ||
969 | case NO_RECOVERY: | |
970 | *statp = EX_SOFTWARE; | |
971 | break; | |
972 | ||
973 | default: | |
974 | *statp = EX_UNAVAILABLE; | |
975 | break; | |
976 | } | |
68d8d275 EA |
977 | #else |
978 | if (tTd(9, 1)) | |
979 | printf("FAIL\n"); | |
980 | *statp = EX_NOHOST; | |
981 | #endif | |
b97dd58b | 982 | s->s_namecanon.nc_stat = *statp; |
365c0831 EA |
983 | if ((*statp != EX_TEMPFAIL && *statp != EX_NOHOST) || |
984 | UseNameServer) | |
d1db7a89 EA |
985 | return NULL; |
986 | ||
987 | /* | |
988 | ** Try to look it up in /etc/hosts | |
989 | */ | |
990 | ||
5b7a2dfe | 991 | hp = sm_gethostbyname(name); |
d1db7a89 EA |
992 | if (hp == NULL) |
993 | { | |
994 | /* no dice there either */ | |
b97dd58b | 995 | s->s_namecanon.nc_stat = *statp = EX_NOHOST; |
d1db7a89 EA |
996 | return NULL; |
997 | } | |
998 | ||
b97dd58b | 999 | s->s_namecanon.nc_stat = *statp = EX_OK; |
3ff91010 EA |
1000 | cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av); |
1001 | s->s_namecanon.nc_cname = newstr(cp); | |
1002 | return cp; | |
1d136a1f | 1003 | } |
42fa5d67 | 1004 | } |
713c523f | 1005 | if ((cp = strchr(name, ']')) == NULL) |
42fa5d67 | 1006 | return (NULL); |
bd974b31 | 1007 | *cp = '\0'; |
d2dc4dd0 | 1008 | in_addr.s_addr = inet_addr(&name[1]); |
740d17b3 | 1009 | |
740d17b3 | 1010 | /* nope -- ask the name server */ |
5b7a2dfe | 1011 | hp = sm_gethostbyaddr((char *)&in_addr, INADDRSZ, AF_INET); |
b97dd58b | 1012 | s->s_namecanon.nc_errno = errno; |
efe7f723 | 1013 | #if NAMED_BIND |
b97dd58b | 1014 | s->s_namecanon.nc_herrno = h_errno; |
68d8d275 | 1015 | #endif |
b97dd58b | 1016 | s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ |
d0432129 | 1017 | if (hp == NULL) |
b97dd58b EA |
1018 | { |
1019 | s->s_namecanon.nc_stat = *statp = EX_NOHOST; | |
42fa5d67 | 1020 | return (NULL); |
b97dd58b | 1021 | } |
42fa5d67 | 1022 | |
740d17b3 | 1023 | /* found a match -- copy out */ |
3ff91010 | 1024 | cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av); |
b97dd58b | 1025 | s->s_namecanon.nc_stat = *statp = EX_OK; |
3ff91010 EA |
1026 | s->s_namecanon.nc_cname = newstr(cp); |
1027 | return cp; | |
217a0102 | 1028 | } |
3341995c EA |
1029 | \f/* |
1030 | ** ANYNET_NTOA -- convert a network address to printable form. | |
1031 | ** | |
1032 | ** Parameters: | |
1033 | ** sap -- a pointer to a sockaddr structure. | |
1034 | ** | |
1035 | ** Returns: | |
1036 | ** A printable version of that sockaddr. | |
1037 | */ | |
1038 | ||
a40faef5 | 1039 | #if NETLINK |
b7c46410 EA |
1040 | # include <net/if_dl.h> |
1041 | #endif | |
1042 | ||
3341995c EA |
1043 | char * |
1044 | anynet_ntoa(sap) | |
1045 | register SOCKADDR *sap; | |
1046 | { | |
1047 | register char *bp; | |
1048 | register char *ap; | |
1049 | int l; | |
13cdecbc | 1050 | static char buf[100]; |
3341995c | 1051 | |
a97feb13 EA |
1052 | /* check for null/zero family */ |
1053 | if (sap == NULL) | |
1054 | return "NULLADDR"; | |
1055 | if (sap->sa.sa_family == 0) | |
1056 | return "0"; | |
1057 | ||
13cdecbc EA |
1058 | switch (sap->sa.sa_family) |
1059 | { | |
a40faef5 | 1060 | #if NETUNIX |
13cdecbc | 1061 | case AF_UNIX: |
2122a474 EA |
1062 | if (sap->sunix.sun_path[0] != '\0') |
1063 | sprintf(buf, "[UNIX: %.64s]", sap->sunix.sun_path); | |
13cdecbc EA |
1064 | else |
1065 | sprintf(buf, "[UNIX: localhost]"); | |
1066 | return buf; | |
1067 | #endif | |
1068 | ||
a40faef5 | 1069 | #if NETINET |
13cdecbc | 1070 | case AF_INET: |
d990f79c | 1071 | return inet_ntoa(sap->sin.sin_addr); |
3356c77c | 1072 | #endif |
3341995c | 1073 | |
a40faef5 | 1074 | #if NETLINK |
b7c46410 EA |
1075 | case AF_LINK: |
1076 | sprintf(buf, "[LINK: %s]", | |
1077 | link_ntoa((struct sockaddr_dl *) &sap->sa)); | |
1078 | return buf; | |
1079 | #endif | |
13cdecbc | 1080 | default: |
b7c46410 EA |
1081 | /* this case is needed when nothing is #defined */ |
1082 | /* in order to keep the switch syntactically correct */ | |
1083 | break; | |
13cdecbc EA |
1084 | } |
1085 | ||
3341995c | 1086 | /* unknown family -- just dump bytes */ |
3356c77c | 1087 | (void) sprintf(buf, "Family %d: ", sap->sa.sa_family); |
3341995c | 1088 | bp = &buf[strlen(buf)]; |
3356c77c EA |
1089 | ap = sap->sa.sa_data; |
1090 | for (l = sizeof sap->sa.sa_data; --l >= 0; ) | |
3341995c EA |
1091 | { |
1092 | (void) sprintf(bp, "%02x:", *ap++ & 0377); | |
1093 | bp += 3; | |
1094 | } | |
1095 | *--bp = '\0'; | |
1096 | return buf; | |
1097 | } | |
3f03d7a7 EA |
1098 | \f/* |
1099 | ** HOSTNAMEBYANYADDR -- return name of host based on address | |
1100 | ** | |
1101 | ** Parameters: | |
1102 | ** sap -- SOCKADDR pointer | |
1103 | ** | |
1104 | ** Returns: | |
1105 | ** text representation of host name. | |
1106 | ** | |
1107 | ** Side Effects: | |
1108 | ** none. | |
1109 | */ | |
1110 | ||
1111 | char * | |
1112 | hostnamebyanyaddr(sap) | |
1113 | register SOCKADDR *sap; | |
1114 | { | |
1115 | register struct hostent *hp; | |
ab6ca5e5 EA |
1116 | int saveretry; |
1117 | ||
efe7f723 | 1118 | #if NAMED_BIND |
ab6ca5e5 EA |
1119 | /* shorten name server timeout to avoid higher level timeouts */ |
1120 | saveretry = _res.retry; | |
1121 | _res.retry = 3; | |
1122 | #endif /* NAMED_BIND */ | |
1123 | ||
3f03d7a7 EA |
1124 | switch (sap->sa.sa_family) |
1125 | { | |
a40faef5 | 1126 | #if NETINET |
3f03d7a7 | 1127 | case AF_INET: |
5b7a2dfe | 1128 | hp = sm_gethostbyaddr((char *) &sap->sin.sin_addr, |
648eb46e | 1129 | INADDRSZ, |
3f03d7a7 EA |
1130 | AF_INET); |
1131 | break; | |
1132 | #endif | |
1133 | ||
a40faef5 | 1134 | #if NETISO |
3f03d7a7 | 1135 | case AF_ISO: |
5b7a2dfe | 1136 | hp = sm_gethostbyaddr((char *) &sap->siso.siso_addr, |
3f03d7a7 EA |
1137 | sizeof sap->siso.siso_addr, |
1138 | AF_ISO); | |
1139 | break; | |
1140 | #endif | |
1141 | ||
13cdecbc EA |
1142 | case AF_UNIX: |
1143 | hp = NULL; | |
1144 | break; | |
13cdecbc | 1145 | |
3f03d7a7 | 1146 | default: |
5b7a2dfe | 1147 | hp = sm_gethostbyaddr(sap->sa.sa_data, |
3f03d7a7 EA |
1148 | sizeof sap->sa.sa_data, |
1149 | sap->sa.sa_family); | |
1150 | break; | |
1151 | } | |
1152 | ||
efe7f723 | 1153 | #if NAMED_BIND |
ab6ca5e5 EA |
1154 | _res.retry = saveretry; |
1155 | #endif /* NAMED_BIND */ | |
1156 | ||
3f03d7a7 EA |
1157 | if (hp != NULL) |
1158 | return hp->h_name; | |
1159 | else | |
1160 | { | |
1161 | /* produce a dotted quad */ | |
1162 | static char buf[512]; | |
1163 | ||
1164 | (void) sprintf(buf, "[%s]", anynet_ntoa(sap)); | |
1165 | return buf; | |
1166 | } | |
1167 | } | |
d0432129 | 1168 | |
f3d8f6d6 | 1169 | # else /* DAEMON */ |
217a0102 | 1170 | /* code for systems without sophisticated networking */ |
2ec2faaa EA |
1171 | |
1172 | /* | |
1173 | ** MYHOSTNAME -- stub version for case of no daemon code. | |
69f904e0 EA |
1174 | ** |
1175 | ** Can't convert to upper case here because might be a UUCP name. | |
05894fc6 EA |
1176 | ** |
1177 | ** Mark, you can change this to be anything you want...... | |
2ec2faaa EA |
1178 | */ |
1179 | ||
1180 | char ** | |
05894fc6 | 1181 | myhostname(hostbuf, size) |
2ec2faaa | 1182 | char hostbuf[]; |
05894fc6 | 1183 | int size; |
2ec2faaa EA |
1184 | { |
1185 | register FILE *f; | |
1186 | ||
1187 | hostbuf[0] = '\0'; | |
1188 | f = fopen("/usr/include/whoami", "r"); | |
1189 | if (f != NULL) | |
1190 | { | |
05894fc6 | 1191 | (void) fgets(hostbuf, size, f); |
2ec2faaa EA |
1192 | fixcrlf(hostbuf, TRUE); |
1193 | (void) fclose(f); | |
1194 | } | |
1195 | return (NULL); | |
1196 | } | |
217a0102 | 1197 | \f/* |
3f03d7a7 | 1198 | ** GETAUTHINFO -- get the real host name asociated with a file descriptor |
5973222c EA |
1199 | ** |
1200 | ** Parameters: | |
1201 | ** fd -- the descriptor | |
1202 | ** | |
1203 | ** Returns: | |
1204 | ** The host name associated with this descriptor, if it can | |
1205 | ** be determined. | |
1206 | ** NULL otherwise. | |
1207 | ** | |
1208 | ** Side Effects: | |
1209 | ** none | |
1210 | */ | |
1211 | ||
1212 | char * | |
3f03d7a7 | 1213 | getauthinfo(fd) |
5973222c EA |
1214 | int fd; |
1215 | { | |
1216 | return NULL; | |
1217 | } | |
1218 | \f/* | |
217a0102 EA |
1219 | ** MAPHOSTNAME -- turn a hostname into canonical form |
1220 | ** | |
1221 | ** Parameters: | |
5a4c03c6 | 1222 | ** map -- a pointer to the database map. |
713c523f | 1223 | ** name -- a buffer containing a hostname. |
42fa5d67 | 1224 | ** avp -- a pointer to a (cf file defined) argument vector. |
d1db7a89 | 1225 | ** statp -- an exit status (out parameter). |
217a0102 EA |
1226 | ** |
1227 | ** Returns: | |
42fa5d67 | 1228 | ** mapped host name |
bbfde42f | 1229 | ** FALSE otherwise. |
217a0102 EA |
1230 | ** |
1231 | ** Side Effects: | |
713c523f | 1232 | ** Looks up the host specified in name. If it is not |
217a0102 EA |
1233 | ** the canonical name for that host, replace it with |
1234 | ** the canonical name. If the name is unknown, or it | |
1235 | ** is already the canonical name, leave it unchanged. | |
1236 | */ | |
1237 | ||
1238 | /*ARGSUSED*/ | |
42fa5d67 | 1239 | char * |
713c523f | 1240 | host_map_lookup(map, name, avp, statp) |
5a4c03c6 | 1241 | MAP *map; |
713c523f | 1242 | char *name; |
42fa5d67 | 1243 | char **avp; |
d1db7a89 | 1244 | char *statp; |
217a0102 | 1245 | { |
d1db7a89 EA |
1246 | register struct hostent *hp; |
1247 | ||
5b7a2dfe | 1248 | hp = sm_gethostbyname(name); |
d1db7a89 EA |
1249 | if (hp != NULL) |
1250 | return hp->h_name; | |
1251 | *statp = EX_NOHOST; | |
42fa5d67 | 1252 | return NULL; |
217a0102 EA |
1253 | } |
1254 | ||
f3d8f6d6 | 1255 | #endif /* DAEMON */ |