1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
|
/* ==================================================================
* CHILD.C
* -------
*
* This module is responsible for running
* xtell as a child service of inetd.
* It cares for this child like a good parent should,
* providing vital nutrients, love, support, child
* reapers, and built in functionality to have the
* child kill itself if it stays alive too long.
*
* ==================================================================
*/
#include "xtelld.h"
#ifndef USE_LIBIDENT
# define ident_id(a,b) NULL
#endif
static int s_in = -1, s_out = -1;
/* ------------------------------------------------------------------
* lookup_addr:
* if resolve_addr, try to reverse resolve the address.
* else return the numerical ip.
* else return the numerical ip.
* ------------------------------------------------------------------
*/
static char *lookup_addr(struct in_addr in)
{
static char addr[MAX_HOSTNAME];
struct hostent *he;
if (resolve_addr) {
he = gethostbyaddr((char *) &in, sizeof(struct in_addr), AF_INET);
if (he == NULL)
strncpy(addr, inet_ntoa(in), sizeof(addr));
else
strncpy(addr, he->h_name, sizeof(addr));
} else
strncpy(addr, inet_ntoa(in), sizeof(addr));
addr[sizeof(addr)-1] = '\0';
return addr;
}
/* ----------------------------------------------------------------
* killtic:
* kill this process after a pre-determined
* timeout period. (SIGALRM handler)
* ----------------------------------------------------------------
*/
void xtell_killtic(int s)
{
killsock(s_in);
killsock(s_out);
exit(0);
}
/* ------------------------------------------------------------------
* inetd_service:
* this function does the actual pipe handling
* user lookups, replies, etcetera. if called
* by the daemon, sd_in and sd_out will be
* the same descriptor, if a child of inetd,
* sd_in will be stdin, sd_out will be stdout
* ------------------------------------------------------------------
*/
void inetd_service(int sd_in, int sd_out)
{
struct in_addr laddr, raddr;
struct sockaddr_in sin;
char buffer[MAX_SOCK_LENGTH];
int sinsize = sizeof(struct sockaddr_in);
short int reqstat;
unsigned int msgcount;
char *identid = NULL;
s_in = sd_in;
s_out = sd_out;
if (getpeername(sd_in, (struct sockaddr *) &sin, &sinsize) == -1) {
syslog(LOG_NOTICE, "error: getpeername: %s", strerror(errno));
client_reply(sd_out, "401 getpeername failed");
return; /* the error implies the net is down, but try */
}
raddr = sin.sin_addr;
if (getsockname(sd_in, (struct sockaddr *) &sin, &sinsize) == -1) {
syslog(LOG_ERR, "error: getsockname: %s", strerror(errno));
client_reply(sd_out, "402 getsockname failed");
return;
}
laddr = sin.sin_addr;
msgcount = 0;
while (1) {
reqstat = get_request(sd_in, buffer, MAX_SOCK_LENGTH);
alarm(client_timeout); /* and reset timeout counter */
if ((reqstat < 0) || (!strncasecmp(buffer, "quit", 4)))
break;
if (msgcount == 0)
identid = ident_id(sd_in, 5);
if (reqstat) {
switch (parse_and_write(buffer, identid, lookup_addr(raddr), ++msgcount)) {
case 0:
client_reply(sd_out, "200 OK, sent.");
break; /* OK */
case -1:
client_reply(sd_out, "403 User is not here.");
break; /* not logged in */
case -2:
client_reply(sd_out, "404 User does not want you.");
break; /* not logged in */
case -3:
client_reply(sd_out,
"405 Cannot write to that user's tty.");
break; /* mesg n or bad tty given */
case -4:
client_reply(sd_out, "406 Ehhh, what?");
break; /* other error */
}
}
}
}
|