- 论坛徽章:
- 0
|
/* mytcpwrap.c
功能:类似著名的 tcpwrap
根据配置文件,允许某些地址的用户进行登陆连接
除可记录登陆时间外,还可以记录退出时间
本程序应由超级服务器inetd启动
使用:替换/etc/inetd.conf 中要进行控制的端口
以telnet、ftp端口控制为例:
/etc/inetd.conf 原内容:
ftp stream tcp nowait root /etc/ftpd ftpd
telnet stream tcp nowait NOLUID /etc/telnetd telnetd
改为:
ftp stream tcp nowait root /etc/mytcpwrap /etc/ftpd
telnet stream tcp nowait NOLUID /etc/mytcpwrap /etc/telnetd
注意:改完后记得通知一下inetd进程
*/
#include "stdio.h"
#include "errno.h"
#include "time.h"
#include "signal.h"
#include ;
#include ;
#include ;
#include ;
#include "sys/stat.h"
#include "sys/times.h"
#define INET_ADDRESTRLEN 18
#define MAXSOCKADDR 64
/* 地址配置文件
格式 port ips
'#' 打头表示本行为注释
'S' 打头表示网络日志记录地,格式为 S port ips
缺省为 5678 1.1.1.1
接受通配符 *
其中 port 记录本地端口,可以使用通配符 * 表示任意端口
ips 允许访问的远程IP地址,形如 nnn.nnn.nnn.nnn
可以使用通配符 * 表示任意地址
例: 21 1.1.1.1 表示1.1.1.1的机器可以访问本机21(ftp)端口
* 2.2.2.2 表示2.2.2.2的机器可以访问本机任意端口
23 3.3.3.* 表示3.3.3.*网段的机器可以访问本机23(telnet)端口
*/
#define INIFILE "/etc/mytcpwrap.conf"
#define LOGFILE "/usr/adm/mytcpwrap.log"
short R_PORT=5678;
char R_ADDR[16]="1.1.1.1";
/* 简单字符串比较函数 */
int cj_Compare(char *so, char *sd)
{
char *to,*td;
int done,cjOk=0,i,k;
if (*sd==0) return 0;
for (done=0,to=so,td=sd;!done; ) {
if (*td=='?') {
td++; to++;
}
else if (*td=='*') {
if (cj_Compare(to,(td+1))==0) return 0;
else to++;
}
else {
cjOk = done = *to - *td;
td++; to++;
}
if (*to==0) for ( ;(*td=='?')||(*td=='*');td++);
if ((*to==0)&&(*td==0)) break;
else if (*to==0) done = cjOk = -1;
else if (*td==0) done = cjOk = -1;
}
return cjOk;
}
int is_denied(char *s, int lport)
{
int k, ct;
char buf[128], ips[32], pts[8];
FILE *fp;
/* 读配置文件 */
fp = fopen(INIFILE, "rt");
if (fp){
memset(buf, 0, sizeof(buf));
fgets(buf, sizeof(buf)-1, fp);
while (!feof(fp)){
memset(pts, 0, sizeof(pts));
memset(ips, 0, sizeof(ips));
sscanf(buf, "%5s%15s", pts, ips);
if (pts[0]!='#'){
if (pts[0]!='S' && pts[0]!='s'){
/* 去除末尾单独的'.' */
while (ips[strlen(ips)-1]=='.') ips[strlen(ips)-1]=0;
for (ct=k=0;k;l){
errno = ENOSPC;
return NULL;
}
strcpy(s, tt);
return tt;
}
errno = EAFNOSUPPORT;
return NULL;
}
sock_ntop(struct sockaddr * sa, int len, char *s)
{
char str[128];
int pt=-1;
struct sockaddr_in *sin=(struct sockaddr_in *)sa;
s[0] = 0;
switch(sa->;sa_family){
case AF_INET:if (inet_ntop(AF_INET, &sin->;sin_addr, str, sizeof(str))==NULL)
return NULL;
pt = ntohs(sin->;sin_port);
strcpy(s, str);
break;
};
return pt;
}
get_time(int t[6])
{
struct tm *tm;
time_t n;
n = time(NULL);
tm = localtime(&n);
t[0] = tm->;tm_year + 1900;
t[1] = tm->;tm_mon+1;
t[2] = tm->;tm_mday;
t[3] = tm->;tm_hour;
t[4] = tm->;tm_min;
t[5] = tm->;tm_sec;
}
long rowid=0;
/* 将登录信息记录到网络上日志服务器上
通过两次提交记录完整的登陆、退出时间
第一次记录登录时间
发送格式: NETLOG|本地服务端口|客户地址|端口|成功标志|
服务端返回一个该记录的rowid值
第二次记录离开时间
发送格式: NETUPD|原记录的rowid
*/
int net_logit(int lport, char *ips, int rport, int succ)
{
int i,s;
struct sockaddr_in sin;
struct hostent *hp;
char buf[128], ss[64];
if (R_PORT==0 || strlen(R_ADDR)==0) return -1;
bzero((char *)&sin,sizeof(sin));
sin.sin_family = AF_INET;
/* 取日志服务器地址 */
hp = gethostbyname(R_ADDR);
if (hp!=NULL)
bcopy(hp->;h_addr, (char *)&sin.sin_addr, hp->;h_length);
else
inet_aton(R_ADDR, &sin.sin_addr);
sin.sin_port = htons(R_PORT);
s = socket(AF_INET, SOCK_STREAM, 0);
if (s
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/19755/showart_160348.html |
|