/*
** iplog_ident.c - iplog IDENT lookup routines.
** Copyright (C) 1999 behe <eric@ojnk.net>, Ryan McCabe <odin@numb.org>
** Copyright (C) 2000-2001 Ryan McCabe <odin@numb.org>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License, version 2,
** as published by the Free Software Foundation.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
**
** $Id: iplog_ident.c,v 1.22 2001/01/01 19:28:07 odin Exp $
*/
#include <config.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#define __FAVOR_BSD
#include <sys/socket.h>
#include <iplog.h>
#include <iplog_options.h>
#define TCP_FORMAT "%*d: %*X:%hx %*X:%*x %x %*X:%*X %*x:%*X %*x %*d %*d %*d"
#define TCP_LISTEN 0x0A
#define TCP_DATA "/proc/net/tcp"
#ifndef __linux__
/*
** Stub functions for platforms other than Linux.
*/
bool is_listening(in_port_t unused) {
(void) unused;
return (false);
}
void *get_ident_data(void *unused) {
(void) unused;
return (NULL);
}
#else
/*
** Request IDENT (RFC 1413) info for the connection specified by "data."
** "data" is a pointer to an IP packet.
** This function is meant to run as its own thread.
*/
void *get_ident_data(void *data) {
int sock;
struct sockaddr_in id_sin;
u_char buf[128], remote_user[64], lbuf[MAX_HSTLEN], sbuf[MAX_SRVLEN];
ssize_t len, blen;
struct ip *ip = (struct ip *) data;
struct tcphdr *tcp = (struct tcphdr *) ((char *) ip + __IP_HDR_LENGTH(ip));
sock = socket(PF_INET, SOCK_STREAM, 0);
if (sock == -1) {
IDEBUG(("[%s:%d] socket: %s", __FILE__, __LINE__, strerror(errno)));
goto ident_fail;
}
id_sin.sin_family = AF_INET;
id_sin.sin_addr.s_addr = ip->ip_src.s_addr;
id_sin.sin_port = htons(113);
if (connect(sock, (struct sockaddr *) &id_sin, sizeof(id_sin)) != 0) {
IDEBUG(("[%s:%d] connect: %s", __FILE__, __LINE__, strerror(errno)));
goto ident_fail;
}
snprintf(buf, sizeof(buf), "%d , %d\r\n",
ntohs(tcp->th_sport), ntohs(tcp->th_dport));
blen = strlen(buf);
if (sock_write(sock, buf, blen) != blen) {
IDEBUG(("[%s:%d] send: %s", __FILE__, __LINE__, strerror(errno)));
goto ident_fail;
}
/* XXX: Fix this to handle being interrupted. */
len = recv(sock, buf, sizeof(buf), 0);
if (len < 1) {
IDEBUG(("[%s:%d] recv: %s", __FILE__, __LINE__, strerror(errno)));
goto ident_fail;
}
buf[len] = '\0';
if (sscanf(buf, "%*u , %*u : USERID :%*[^:]:%64s", remote_user) == 1) {
if (opt_enabled(LOG_DEST)) {
u_char lbuf2[MAX_HSTLEN];
mysyslog("TCP: %s connection attempt to %s from %s@%s:%u",
serv_lookup(tcp->th_dport, "tcp", sbuf, sizeof(sbuf)),
host_lookup(&ip->ip_dst, tcp_res(), lbuf2, sizeof(lbuf2)),
remote_user,
host_lookup(&ip->ip_src, tcp_res(), lbuf, sizeof(lbuf)),
ntohs(tcp->th_sport));
} else {
mysyslog("TCP: %s connection attempt from %s@%s:%u",
serv_lookup(tcp->th_dport, "tcp", sbuf, sizeof(sbuf)), remote_user,
host_lookup(&ip->ip_src, tcp_res(), lbuf, sizeof(lbuf)),
ntohs(tcp->th_sport));
}
free(data);
close(sock);
return (NULL);
} else
IDEBUG(("[%s:%d] Bad ident response: %s", __FILE__, __LINE__, buf));
ident_fail:
if (opt_enabled(LOG_DEST)) {
u_char lbuf2[MAX_HSTLEN];
mysyslog("TCP: %s connection attempt to %s from %s:%u",
serv_lookup(tcp->th_dport, "tcp", sbuf, sizeof(sbuf)),
host_lookup(&ip->ip_dst, tcp_res(), lbuf2, sizeof(lbuf2)),
host_lookup(&ip->ip_src, tcp_res(), lbuf, sizeof(lbuf)),
ntohs(tcp->th_sport));
} else {
mysyslog("TCP: %s connection attempt from %s:%u",
serv_lookup(tcp->th_dport, "tcp", sbuf, sizeof(sbuf)),
host_lookup(&ip->ip_src, tcp_res(), lbuf, sizeof(lbuf)),
ntohs(tcp->th_sport));
}
free(data);
close(sock);
return (NULL);
}
/*
** Returns true if local port "port" is open and listening, false if it isn't.
*/
bool is_listening(in_port_t port) {
FILE *fp;
in_port_t lport;
u_int mode;
u_char buf[1024];
port = htons(port);
fp = fopen(TCP_DATA, "r");
if (fp == NULL)
return (false);
while (get_line(fp, buf, sizeof(buf) - 1) != EOF) {
if (sscanf(buf, TCP_FORMAT, &lport, &mode) != 2)
continue;
if (lport == port) {
if (mode == TCP_LISTEN) {
fclose(fp);
return (true);
}
break;
}
}
fclose(fp);
return (false);
}
#endif /* __linux__ */
/* vim:ts=4:sw=8:tw=0 */
syntax highlighted by Code2HTML, v. 0.9.1