identd.c revision 1.1 1 1.1 cgd /*
2 1.1 cgd ** identd.c A TCP/IP link identification protocol server
3 1.1 cgd **
4 1.1 cgd ** This program is in the public domain and may be used freely by anyone
5 1.1 cgd ** who wants to.
6 1.1 cgd **
7 1.1 cgd ** Last update: 22 April 1993
8 1.1 cgd **
9 1.1 cgd ** Please send bug fixes/bug reports to: Peter Eriksson <pen (at) lysator.liu.se>
10 1.1 cgd */
11 1.1 cgd
12 1.1 cgd #if defined(IRIX) || defined(SVR4) || defined(NeXT)
13 1.1 cgd # define SIGRETURN_TYPE void
14 1.1 cgd # define SIGRETURN_TYPE_IS_VOID
15 1.1 cgd #else
16 1.1 cgd # define SIGRETURN_TYPE int
17 1.1 cgd #endif
18 1.1 cgd
19 1.1 cgd #ifdef SVR4
20 1.1 cgd # define STRNET
21 1.1 cgd #endif
22 1.1 cgd
23 1.1 cgd #include <stdio.h>
24 1.1 cgd #include <ctype.h>
25 1.1 cgd #include <errno.h>
26 1.1 cgd #include <netdb.h>
27 1.1 cgd #include <signal.h>
28 1.1 cgd #include <fcntl.h>
29 1.1 cgd
30 1.1 cgd #include <sys/types.h>
31 1.1 cgd #include <sys/param.h>
32 1.1 cgd #include <sys/ioctl.h>
33 1.1 cgd #include <sys/socket.h>
34 1.1 cgd #ifndef _AUX_SOURCE
35 1.1 cgd # include <sys/file.h>
36 1.1 cgd #endif
37 1.1 cgd #include <sys/time.h>
38 1.1 cgd #include <sys/wait.h>
39 1.1 cgd
40 1.1 cgd #include <pwd.h>
41 1.1 cgd #include <grp.h>
42 1.1 cgd
43 1.1 cgd #include <netinet/in.h>
44 1.1 cgd
45 1.1 cgd #ifndef HPUX7
46 1.1 cgd # include <arpa/inet.h>
47 1.1 cgd #endif
48 1.1 cgd
49 1.1 cgd #if defined(MIPS) || defined(BSD43)
50 1.1 cgd extern int errno;
51 1.1 cgd #endif
52 1.1 cgd
53 1.1 cgd #include "identd.h"
54 1.1 cgd #include "error.h"
55 1.1 cgd
56 1.1 cgd /* Antique unixes do not have these things defined... */
57 1.1 cgd #ifndef FD_SETSIZE
58 1.1 cgd # define FD_SETSIZE 256
59 1.1 cgd #endif
60 1.1 cgd
61 1.1 cgd #ifndef FD_SET
62 1.1 cgd # ifndef NFDBITS
63 1.1 cgd # define NFDBITS (sizeof(int) * NBBY) /* bits per mask */
64 1.1 cgd # endif
65 1.1 cgd # define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
66 1.1 cgd #endif
67 1.1 cgd
68 1.1 cgd #ifndef FD_ZERO
69 1.1 cgd # define FD_ZERO(p) bzero((char *)(p), sizeof(*(p)))
70 1.1 cgd #endif
71 1.1 cgd
72 1.1 cgd extern char *version;
73 1.1 cgd
74 1.1 cgd extern void *calloc();
75 1.1 cgd extern void *malloc();
76 1.1 cgd
77 1.1 cgd
78 1.1 cgd char *path_unix = NULL;
79 1.1 cgd char *path_kmem = NULL;
80 1.1 cgd
81 1.1 cgd int verbose_flag = 0;
82 1.1 cgd int debug_flag = 0;
83 1.1 cgd int syslog_flag = 0;
84 1.1 cgd int multi_flag = 0;
85 1.1 cgd int other_flag = 0;
86 1.1 cgd int unknown_flag = 0;
87 1.1 cgd int number_flag = 0;
88 1.1 cgd int noident_flag = 0;
89 1.1 cgd
90 1.1 cgd int lport = 0;
91 1.1 cgd int fport = 0;
92 1.1 cgd
93 1.1 cgd char *charset_name = NULL;
94 1.1 cgd char *indirect_host = NULL;
95 1.1 cgd char *indirect_password = NULL;
96 1.1 cgd
97 1.1 cgd static int child_pid;
98 1.1 cgd
99 1.1 cgd #ifdef LOG_DAEMON
100 1.1 cgd static int syslog_facility = LOG_DAEMON;
101 1.1 cgd #endif
102 1.1 cgd
103 1.1 cgd /*
104 1.1 cgd ** The structure passing convention for GCC is incompatible with
105 1.1 cgd ** Suns own C compiler, so we define our own inet_ntoa() function.
106 1.1 cgd ** (This should only affect GCC version 1 I think, a well, this works
107 1.1 cgd ** for version 2 also so why bother.. :-)
108 1.1 cgd */
109 1.1 cgd #if defined(__GNUC__) && defined(__sparc__)
110 1.1 cgd
111 1.1 cgd #ifdef inet_ntoa
112 1.1 cgd #undef inet_ntoa
113 1.1 cgd #endif
114 1.1 cgd
115 1.1 cgd char *inet_ntoa(ad)
116 1.1 cgd struct in_addr ad;
117 1.1 cgd {
118 1.1 cgd unsigned long int s_ad;
119 1.1 cgd int a, b, c, d;
120 1.1 cgd static char addr[20];
121 1.1 cgd
122 1.1 cgd s_ad = ad.s_addr;
123 1.1 cgd d = s_ad % 256;
124 1.1 cgd s_ad /= 256;
125 1.1 cgd c = s_ad % 256;
126 1.1 cgd s_ad /= 256;
127 1.1 cgd b = s_ad % 256;
128 1.1 cgd a = s_ad / 256;
129 1.1 cgd sprintf(addr, "%d.%d.%d.%d", a, b, c, d);
130 1.1 cgd
131 1.1 cgd return addr;
132 1.1 cgd }
133 1.1 cgd #endif
134 1.1 cgd
135 1.1 cgd
136 1.1 cgd /*
137 1.1 cgd ** Return the name of the connecting host, or the IP number as a string.
138 1.1 cgd */
139 1.1 cgd char *gethost(addr)
140 1.1 cgd struct in_addr *addr;
141 1.1 cgd {
142 1.1 cgd struct hostent *hp;
143 1.1 cgd
144 1.1 cgd
145 1.1 cgd hp = gethostbyaddr((char *) addr, sizeof(struct in_addr), AF_INET);
146 1.1 cgd if (hp)
147 1.1 cgd return hp->h_name;
148 1.1 cgd else
149 1.1 cgd return inet_ntoa(*addr);
150 1.1 cgd }
151 1.1 cgd
152 1.1 cgd #ifdef USE_SIGALARM
153 1.1 cgd /*
154 1.1 cgd ** Exit cleanly after our time's up.
155 1.1 cgd */
156 1.1 cgd static SIGRETURN_TYPE
157 1.1 cgd alarm_handler()
158 1.1 cgd {
159 1.1 cgd if (syslog_flag)
160 1.1 cgd syslog(LOG_DEBUG, "SIGALRM triggered, exiting");
161 1.1 cgd
162 1.1 cgd exit(0);
163 1.1 cgd }
164 1.1 cgd #endif
165 1.1 cgd
166 1.1 cgd
167 1.1 cgd #if !defined(hpux) && !defined(__hpux) && !defined(SVR4) || defined(_CRAY)
168 1.1 cgd /*
169 1.1 cgd ** This is used to clean up zombie child processes
170 1.1 cgd ** if the -w or -b options are used.
171 1.1 cgd */
172 1.1 cgd static SIGRETURN_TYPE
173 1.1 cgd child_handler()
174 1.1 cgd {
175 1.1 cgd #if defined(IRIX) || defined(NeXT)
176 1.1 cgd union wait status;
177 1.1 cgd #else
178 1.1 cgd int status;
179 1.1 cgd #endif
180 1.1 cgd
181 1.1 cgd while (wait3(&status, WNOHANG, NULL) > 0)
182 1.1 cgd ;
183 1.1 cgd
184 1.1 cgd #ifndef SIGRETURN_TYPE_IS_VOID
185 1.1 cgd return 0;
186 1.1 cgd #endif
187 1.1 cgd }
188 1.1 cgd #endif
189 1.1 cgd
190 1.1 cgd
191 1.1 cgd char *clearmem(bp, len)
192 1.1 cgd char *bp;
193 1.1 cgd int len;
194 1.1 cgd {
195 1.1 cgd char *cp;
196 1.1 cgd
197 1.1 cgd cp = bp;
198 1.1 cgd while (len-- > 0)
199 1.1 cgd *cp++ = 0;
200 1.1 cgd
201 1.1 cgd return bp;
202 1.1 cgd }
203 1.1 cgd
204 1.1 cgd
205 1.1 cgd /*
206 1.1 cgd ** Main entry point into this daemon
207 1.1 cgd */
208 1.1 cgd int main(argc,argv)
209 1.1 cgd int argc;
210 1.1 cgd char *argv[];
211 1.1 cgd {
212 1.1 cgd int i, len;
213 1.1 cgd struct sockaddr_in sin;
214 1.1 cgd struct in_addr laddr, faddr;
215 1.1 cgd #ifndef USE_SIGALARM
216 1.1 cgd struct timeval tv;
217 1.1 cgd #endif
218 1.1 cgd
219 1.1 cgd int background_flag = 0;
220 1.1 cgd int timeout = 0;
221 1.1 cgd char *portno = "113";
222 1.1 cgd char *bind_address = NULL;
223 1.1 cgd int set_uid = 0;
224 1.1 cgd int set_gid = 0;
225 1.1 cgd int inhibit_default_config = 0;
226 1.1 cgd int opt_count = 0; /* Count of option flags */
227 1.1 cgd
228 1.1 cgd #ifdef __convex__
229 1.1 cgd argc--; /* get rid of extra argument passed by inetd */
230 1.1 cgd #endif
231 1.1 cgd
232 1.1 cgd /*
233 1.1 cgd ** Prescan the arguments for "-f<config-file>" switches
234 1.1 cgd */
235 1.1 cgd inhibit_default_config = 0;
236 1.1 cgd for (i = 1; i < argc && argv[i][0] == '-'; i++)
237 1.1 cgd if (argv[i][1] == 'f')
238 1.1 cgd inhibit_default_config = 1;
239 1.1 cgd
240 1.1 cgd /*
241 1.1 cgd ** Parse the default config file - if it exists
242 1.1 cgd */
243 1.1 cgd if (!inhibit_default_config)
244 1.1 cgd parse_config(NULL, 1);
245 1.1 cgd
246 1.1 cgd /*
247 1.1 cgd ** Parse the command line arguments
248 1.1 cgd */
249 1.1 cgd for (i = 1; i < argc && argv[i][0] == '-'; i++) {
250 1.1 cgd opt_count++;
251 1.1 cgd switch (argv[i][1])
252 1.1 cgd {
253 1.1 cgd case 'b': /* Start as standalone daemon */
254 1.1 cgd background_flag = 1;
255 1.1 cgd break;
256 1.1 cgd
257 1.1 cgd case 'w': /* Start from Inetd, wait mode */
258 1.1 cgd background_flag = 2;
259 1.1 cgd break;
260 1.1 cgd
261 1.1 cgd case 'i': /* Start from Inetd, nowait mode */
262 1.1 cgd background_flag = 0;
263 1.1 cgd break;
264 1.1 cgd
265 1.1 cgd case 't':
266 1.1 cgd timeout = atoi(argv[i]+2);
267 1.1 cgd break;
268 1.1 cgd
269 1.1 cgd case 'p':
270 1.1 cgd portno = argv[i]+2;
271 1.1 cgd break;
272 1.1 cgd
273 1.1 cgd case 'a':
274 1.1 cgd bind_address = argv[i]+2;
275 1.1 cgd break;
276 1.1 cgd
277 1.1 cgd case 'u':
278 1.1 cgd if (isdigit(argv[i][2]))
279 1.1 cgd set_uid = atoi(argv[i]+2);
280 1.1 cgd else
281 1.1 cgd {
282 1.1 cgd struct passwd *pwd;
283 1.1 cgd
284 1.1 cgd pwd = getpwnam(argv[i]+2);
285 1.1 cgd if (!pwd)
286 1.1 cgd ERROR1("no such user (%s) for -u option", argv[i]+2);
287 1.1 cgd else
288 1.1 cgd {
289 1.1 cgd set_uid = pwd->pw_uid;
290 1.1 cgd set_gid = pwd->pw_gid;
291 1.1 cgd }
292 1.1 cgd }
293 1.1 cgd break;
294 1.1 cgd
295 1.1 cgd case 'g':
296 1.1 cgd if (isdigit(argv[i][2]))
297 1.1 cgd set_gid = atoi(argv[i]+2);
298 1.1 cgd else
299 1.1 cgd {
300 1.1 cgd struct group *grp;
301 1.1 cgd
302 1.1 cgd grp = getgrnam(argv[i]+2);
303 1.1 cgd if (!grp)
304 1.1 cgd ERROR1("no such group (%s) for -g option", argv[i]+2);
305 1.1 cgd else
306 1.1 cgd set_gid = grp->gr_gid;
307 1.1 cgd }
308 1.1 cgd break;
309 1.1 cgd
310 1.1 cgd case 'c':
311 1.1 cgd charset_name = argv[i]+2;
312 1.1 cgd break;
313 1.1 cgd
314 1.1 cgd case 'r':
315 1.1 cgd indirect_host = argv[i]+2;
316 1.1 cgd break;
317 1.1 cgd
318 1.1 cgd case 'l': /* Use the Syslog daemon for logging */
319 1.1 cgd syslog_flag++;
320 1.1 cgd break;
321 1.1 cgd
322 1.1 cgd case 'o':
323 1.1 cgd other_flag = 1;
324 1.1 cgd break;
325 1.1 cgd
326 1.1 cgd case 'e':
327 1.1 cgd unknown_flag = 1;
328 1.1 cgd break;
329 1.1 cgd
330 1.1 cgd case 'n':
331 1.1 cgd number_flag = 1;
332 1.1 cgd break;
333 1.1 cgd
334 1.1 cgd case 'V': /* Give version of this daemon */
335 1.1 cgd printf("[in.identd, version %s]\r\n", version);
336 1.1 cgd exit(0);
337 1.1 cgd break;
338 1.1 cgd
339 1.1 cgd case 'v': /* Be verbose */
340 1.1 cgd verbose_flag++;
341 1.1 cgd break;
342 1.1 cgd
343 1.1 cgd case 'd': /* Enable debugging */
344 1.1 cgd debug_flag++;
345 1.1 cgd break;
346 1.1 cgd
347 1.1 cgd case 'm': /* Enable multiline queries */
348 1.1 cgd multi_flag++;
349 1.1 cgd break;
350 1.1 cgd
351 1.1 cgd case 'N': /* Enable users ".noident" files */
352 1.1 cgd noident_flag++;
353 1.1 cgd break;
354 1.1 cgd }
355 1.1 cgd }
356 1.1 cgd
357 1.1 cgd #if defined(_AUX_SOURCE) || defined (SUNOS35)
358 1.1 cgd /* A/UX 2.0* & SunOS 3.5 calls us with an argument XXXXXXXX.YYYY
359 1.1 cgd ** where XXXXXXXXX is the hexadecimal version of the callers
360 1.1 cgd ** IP number, and YYYY is the port/socket or something.
361 1.1 cgd ** It seems to be impossible to pass arguments to a daemon started
362 1.1 cgd ** by inetd.
363 1.1 cgd **
364 1.1 cgd ** Just in case it is started from something else, then we only
365 1.1 cgd ** skip the argument if no option flags have been seen.
366 1.1 cgd */
367 1.1 cgd if (opt_count == 0)
368 1.1 cgd argc--;
369 1.1 cgd #endif
370 1.1 cgd
371 1.1 cgd /*
372 1.1 cgd ** Path to kernel namelist file specified on command line
373 1.1 cgd */
374 1.1 cgd if (i < argc)
375 1.1 cgd path_unix = argv[i++];
376 1.1 cgd
377 1.1 cgd /*
378 1.1 cgd ** Path to kernel memory device specified on command line
379 1.1 cgd */
380 1.1 cgd if (i < argc)
381 1.1 cgd path_kmem = argv[i++];
382 1.1 cgd
383 1.1 cgd
384 1.1 cgd /*
385 1.1 cgd ** Open the kernel memory device and read the nlist table
386 1.1 cgd */
387 1.1 cgd if (k_open() < 0)
388 1.1 cgd ERROR("main: k_open");
389 1.1 cgd
390 1.1 cgd /*
391 1.1 cgd ** Do the special handling needed for the "-b" flag
392 1.1 cgd */
393 1.1 cgd if (background_flag == 1)
394 1.1 cgd {
395 1.1 cgd struct sockaddr_in addr;
396 1.1 cgd struct servent *sp;
397 1.1 cgd int fd;
398 1.1 cgd
399 1.1 cgd
400 1.1 cgd if (fork())
401 1.1 cgd exit(0);
402 1.1 cgd
403 1.1 cgd close(0);
404 1.1 cgd close(1);
405 1.1 cgd close(2);
406 1.1 cgd
407 1.1 cgd if (fork())
408 1.1 cgd exit(0);
409 1.1 cgd
410 1.1 cgd fd = socket(AF_INET, SOCK_STREAM, 0);
411 1.1 cgd if (fd == -1)
412 1.1 cgd ERROR("main: socket");
413 1.1 cgd
414 1.1 cgd if (fd != 0)
415 1.1 cgd dup2(fd, 0);
416 1.1 cgd
417 1.1 cgd clearmem(&addr, sizeof(addr));
418 1.1 cgd
419 1.1 cgd addr.sin_family = AF_INET;
420 1.1 cgd if (bind_address == NULL)
421 1.1 cgd addr.sin_addr.s_addr = htonl(INADDR_ANY);
422 1.1 cgd else
423 1.1 cgd {
424 1.1 cgd if (isdigit(bind_address[0]))
425 1.1 cgd addr.sin_addr.s_addr = inet_addr(bind_address);
426 1.1 cgd else
427 1.1 cgd {
428 1.1 cgd struct hostent *hp;
429 1.1 cgd
430 1.1 cgd hp = gethostbyname(bind_address);
431 1.1 cgd if (!hp)
432 1.1 cgd ERROR1("no such address (%s) for -a switch", bind_address);
433 1.1 cgd
434 1.1 cgd /* This is ugly, should use memcpy() or bcopy() but... */
435 1.1 cgd addr.sin_addr.s_addr = * (unsigned long *) (hp->h_addr);
436 1.1 cgd }
437 1.1 cgd }
438 1.1 cgd
439 1.1 cgd if (isdigit(portno[0]))
440 1.1 cgd addr.sin_port = htons(atoi(portno));
441 1.1 cgd else
442 1.1 cgd {
443 1.1 cgd sp = getservbyname(portno, "tcp");
444 1.1 cgd if (sp == NULL)
445 1.1 cgd ERROR1("main: getservbyname: %s", portno);
446 1.1 cgd addr.sin_port = sp->s_port;
447 1.1 cgd }
448 1.1 cgd
449 1.1 cgd if (bind(0, (struct sockaddr *) &addr, sizeof(addr)) < 0)
450 1.1 cgd ERROR("main: bind");
451 1.1 cgd
452 1.1 cgd if (listen(0, 3) < 0)
453 1.1 cgd ERROR("main: listen");
454 1.1 cgd }
455 1.1 cgd
456 1.1 cgd if (set_gid)
457 1.1 cgd if (setgid(set_gid) == -1)
458 1.1 cgd ERROR("main: setgid");
459 1.1 cgd
460 1.1 cgd if (set_uid)
461 1.1 cgd if (setuid(set_uid) == -1)
462 1.1 cgd ERROR("main: setuid");
463 1.1 cgd
464 1.1 cgd /*
465 1.1 cgd ** Do some special handling if the "-b" or "-w" flags are used
466 1.1 cgd */
467 1.1 cgd if (background_flag)
468 1.1 cgd {
469 1.1 cgd int nfds, fd;
470 1.1 cgd fd_set read_set;
471 1.1 cgd
472 1.1 cgd
473 1.1 cgd /*
474 1.1 cgd ** Set up the SIGCHLD signal child termination handler so
475 1.1 cgd ** that we can avoid zombie processes hanging around and
476 1.1 cgd ** handle childs terminating before being able to complete the
477 1.1 cgd ** handshake.
478 1.1 cgd */
479 1.1 cgd #if (defined(SVR4) || defined(hpux) || defined(__hpux) || \
480 1.1 cgd defined(_CRAY) || defined(_AUX_SOURCE))
481 1.1 cgd signal(SIGCHLD, SIG_IGN);
482 1.1 cgd #else
483 1.1 cgd signal(SIGCHLD, (SIGRETURN_TYPE (*)()) child_handler);
484 1.1 cgd #endif
485 1.1 cgd
486 1.1 cgd /*
487 1.1 cgd ** Loop and dispatch client handling processes
488 1.1 cgd */
489 1.1 cgd do
490 1.1 cgd {
491 1.1 cgd #ifdef USE_SIGALARM
492 1.1 cgd /*
493 1.1 cgd ** Terminate if we've been idle for 'timeout' seconds
494 1.1 cgd */
495 1.1 cgd if (background_flag == 2 && timeout)
496 1.1 cgd {
497 1.1 cgd signal(SIGALRM, alarm_handler);
498 1.1 cgd alarm(timeout);
499 1.1 cgd }
500 1.1 cgd #endif
501 1.1 cgd
502 1.1 cgd /*
503 1.1 cgd ** Wait for a connection request to occur.
504 1.1 cgd ** Ignore EINTR (Interrupted System Call).
505 1.1 cgd */
506 1.1 cgd do
507 1.1 cgd {
508 1.1 cgd FD_ZERO(&read_set);
509 1.1 cgd FD_SET(0, &read_set);
510 1.1 cgd
511 1.1 cgd #ifndef USE_SIGALARM
512 1.1 cgd if (timeout)
513 1.1 cgd {
514 1.1 cgd tv.tv_sec = timeout;
515 1.1 cgd tv.tv_usec = 0;
516 1.1 cgd nfds = select(FD_SETSIZE, &read_set, NULL, NULL, &tv);
517 1.1 cgd }
518 1.1 cgd else
519 1.1 cgd #endif
520 1.1 cgd
521 1.1 cgd nfds = select(FD_SETSIZE, &read_set, NULL, NULL, NULL);
522 1.1 cgd } while (nfds < 0 && errno == EINTR);
523 1.1 cgd
524 1.1 cgd /*
525 1.1 cgd ** An error occured in select? Just die
526 1.1 cgd */
527 1.1 cgd if (nfds < 0)
528 1.1 cgd ERROR("main: select");
529 1.1 cgd
530 1.1 cgd /*
531 1.1 cgd ** Timeout limit reached. Exit nicely
532 1.1 cgd */
533 1.1 cgd if (nfds == 0)
534 1.1 cgd exit(0);
535 1.1 cgd
536 1.1 cgd #ifdef USE_SIGALARM
537 1.1 cgd /*
538 1.1 cgd ** Disable the alarm timeout
539 1.1 cgd */
540 1.1 cgd alarm(0);
541 1.1 cgd #endif
542 1.1 cgd
543 1.1 cgd /*
544 1.1 cgd ** Accept the new client
545 1.1 cgd */
546 1.1 cgd fd = accept(0, NULL, NULL);
547 1.1 cgd if (fd == -1)
548 1.1 cgd ERROR1("main: accept. errno = %d", errno);
549 1.1 cgd
550 1.1 cgd /*
551 1.1 cgd ** And fork, then close the fd if we are the parent.
552 1.1 cgd */
553 1.1 cgd child_pid = fork();
554 1.1 cgd } while (child_pid && (close(fd), 1));
555 1.1 cgd
556 1.1 cgd /*
557 1.1 cgd ** We are now in child, the parent has returned to "do" above.
558 1.1 cgd */
559 1.1 cgd if (dup2(fd, 0) == -1)
560 1.1 cgd ERROR("main: dup2: failed fd 0");
561 1.1 cgd
562 1.1 cgd if (dup2(fd, 1) == -1)
563 1.1 cgd ERROR("main: dup2: failed fd 1");
564 1.1 cgd
565 1.1 cgd if (dup2(fd, 2) == -1)
566 1.1 cgd ERROR("main: dup2: failed fd 2");
567 1.1 cgd }
568 1.1 cgd
569 1.1 cgd /*
570 1.1 cgd ** Get foreign internet address
571 1.1 cgd */
572 1.1 cgd len = sizeof(sin);
573 1.1 cgd if (getpeername(0, (struct sockaddr *) &sin, &len) == -1)
574 1.1 cgd {
575 1.1 cgd /*
576 1.1 cgd ** A user has tried to start us from the command line or
577 1.1 cgd ** the network link died, in which case this message won't
578 1.1 cgd ** reach to other end anyway, so lets give the poor user some
579 1.1 cgd ** errors.
580 1.1 cgd */
581 1.1 cgd perror("in.identd: getpeername()");
582 1.1 cgd exit(1);
583 1.1 cgd }
584 1.1 cgd
585 1.1 cgd faddr = sin.sin_addr;
586 1.1 cgd
587 1.1 cgd
588 1.1 cgd /*
589 1.1 cgd ** Open the connection to the Syslog daemon if requested
590 1.1 cgd */
591 1.1 cgd if (syslog_flag)
592 1.1 cgd {
593 1.1 cgd #ifdef LOG_DAEMON
594 1.1 cgd openlog("identd", LOG_PID, syslog_facility);
595 1.1 cgd #else
596 1.1 cgd openlog("identd", LOG_PID);
597 1.1 cgd #endif
598 1.1 cgd
599 1.1 cgd syslog(LOG_INFO, "Connection from %s", gethost(&faddr));
600 1.1 cgd }
601 1.1 cgd
602 1.1 cgd
603 1.1 cgd /*
604 1.1 cgd ** Get local internet address
605 1.1 cgd */
606 1.1 cgd len = sizeof(sin);
607 1.1 cgd #ifdef ATTSVR4
608 1.1 cgd if (t_getsockname(0, (struct sockaddr *) &sin, &len) == -1)
609 1.1 cgd #else
610 1.1 cgd if (getsockname(0, (struct sockaddr *) &sin, &len) == -1)
611 1.1 cgd #endif
612 1.1 cgd {
613 1.1 cgd /*
614 1.1 cgd ** We can just die here, because if this fails then the
615 1.1 cgd ** network has died and we haven't got anyone to return
616 1.1 cgd ** errors to.
617 1.1 cgd */
618 1.1 cgd exit(1);
619 1.1 cgd }
620 1.1 cgd laddr = sin.sin_addr;
621 1.1 cgd
622 1.1 cgd
623 1.1 cgd /*
624 1.1 cgd ** Get the local/foreign port pair from the luser
625 1.1 cgd */
626 1.1 cgd parse(stdin, &laddr, &faddr);
627 1.1 cgd
628 1.1 cgd exit(0);
629 1.1 cgd }
630