⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 common.c

📁 NAT协议完整源代码
💻 C
字号:
/* * Copyright (C) 1993-2000 by Darren Reed. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and due credit is given * to the original author and the contributors. */#include <sys/types.h>#if !defined(__SVR4) && !defined(__svr4__)#include <strings.h>#else#include <sys/byteorder.h>#endif#include <sys/param.h>#include <sys/time.h>#include <sys/socket.h>#include <netinet/in.h>#include <netinet/in_systm.h>#include <netinet/ip.h>#include <netinet/tcp.h>#include <net/if.h>#if __FreeBSD_version >= 300000# include <net/if_var.h>#endif#include <stdio.h>#include <string.h>#include <limits.h>#include <stdlib.h>#include <unistd.h>#include <stddef.h>#include <netdb.h>#include <arpa/nameser.h>#include <arpa/inet.h>#include <resolv.h>#include <ctype.h>#include <syslog.h>#include "ip_compat.h"#include "ip_fil.h"#include "ipf.h"#include "facpri.h"#if !defined(lint)static const char sccsid[] = "@(#)parse.c	1.44 6/5/96 (C) 1993-2000 Darren Reed";static const char rcsid[] = "@(#)$IPFilter: parse.c,v 2.8 1999/12/28 10:49:46 darrenr Exp $";#endifextern	struct	ipopt_names	ionames[], secclass[];extern	int	opts;#ifdef	USE_INET6extern	int	use_inet6;#endifchar	*proto = NULL;char	flagset[] = "FSRPAUEC";u_char	flags[] = { TH_FIN, TH_SYN, TH_RST, TH_PUSH, TH_ACK, TH_URG,		    TH_ECN, TH_CWR };#ifdef	USE_INET6void fill6bits __P((int, u_32_t *));int count6bits __P((u_32_t *));#endifstatic	char	thishost[MAXHOSTNAMELEN];void initparse(){	gethostname(thishost, sizeof(thishost));	thishost[sizeof(thishost) - 1] = '\0';}int genmask(msk, mskp)char *msk;u_32_t *mskp;{	char *endptr = NULL;#ifdef	USE_INET6	u_32_t addr;#endif	int bits;	if (index(msk, '.') || index(msk, 'x') || index(msk, ':')) {		/* possibly of the form xxx.xxx.xxx.xxx		 * or 0xYYYYYYYY */#ifdef	USE_INET6		if (use_inet6) {			if (inet_pton(AF_INET6, msk, &addr) != 1)				return -1;		} else#endif		if (inet_aton(msk, (struct in_addr *)mskp) == 0)			return -1;	} else {		/*		 * set x most significant bits		 */		bits = (int)strtol(msk, &endptr, 0);#ifdef	USE_INET6		if ((*endptr != '\0') ||		    ((bits > 32) && !use_inet6) || (bits < 0) ||		    ((bits > 128) && use_inet6))#else		if (*endptr != '\0' || bits > 32 || bits < 0)#endif			return -1;#ifdef	USE_INET6		if (use_inet6)			fill6bits(bits, mskp);		else#endif		if (bits == 0)			*mskp = 0;		else			*mskp = htonl(0xffffffff << (32 - bits));	}	return 0;}#ifdef	USE_INET6void fill6bits(bits, msk)int bits;u_32_t *msk;{	int i;		for (i = 0; bits >= 32 && i < 4 ; ++i, bits -= 32)		msk[i] = 0xffffffff;		if (bits > 0 && i < 4)		msk[i++] = htonl(0xffffffff << (32 - bits));	while (i < 4)		msk[i++] = 0;}#endif/* * returns -1 if neither "hostmask/num" or "hostmask mask addr" are * found in the line segments, there is an error processing this information, * or there is an error processing ports information. */int	hostmask(seg, sa, msk, pp, cp, tp, linenum)char	***seg;u_32_t	*sa, *msk;u_short	*pp, *tp;int	*cp;int	linenum;{	struct in_addr maskaddr;	char *s;	/*	 * is it possibly hostname/num ?	 */	if ((s = index(**seg, '/')) ||	    ((s = index(**seg, ':')) && !index(s + 1, ':'))) {		*s++ = '\0';		if (genmask(s, msk) == -1) {			fprintf(stderr, "%d: bad mask (%s)\n", linenum, s);			return -1;		}		if (hostnum(sa, **seg, linenum) == -1) {			fprintf(stderr, "%d: bad host (%s)\n", linenum, **seg);			return -1;		}		*sa &= *msk;		(*seg)++;		return ports(seg, pp, cp, tp, linenum);	}	/*	 * look for extra segments if "mask" found in right spot	 */	if (*(*seg+1) && *(*seg+2) && !strcasecmp(*(*seg+1), "mask")) {		if (hostnum(sa, **seg, linenum) == -1) {			fprintf(stderr, "%d: bad host (%s)\n", linenum, **seg);			return -1;		}		(*seg)++;		(*seg)++;		if (inet_aton(**seg, &maskaddr) == 0) {			fprintf(stderr, "%d: bad mask (%s)\n", linenum, **seg);			return -1;		}		*msk = maskaddr.s_addr;		(*seg)++;		*sa &= *msk;		return ports(seg, pp, cp, tp, linenum);	}	if (**seg) {		if (hostnum(sa, **seg, linenum) == -1) {			fprintf(stderr, "%d: bad host (%s)\n", linenum, **seg);			return -1;		}		(*seg)++;#ifdef	USE_INET6		if (use_inet6) {			u_32_t k = 0;			if (sa[0] || sa[1] || sa[2] || sa[3])				k = 0xffffffff;			msk[0] = msk[1] = msk[2] = msk[3] = k;		}		else#endif		*msk = *sa ? 0xffffffff : 0;		return ports(seg, pp, cp, tp, linenum);	}	fprintf(stderr, "%d: bad host (%s)\n", linenum, **seg);	return -1;}/* * returns an ip address as a long var as a result of either a DNS lookup or * straight inet_addr() call */int	hostnum(ipa, host, linenum)u_32_t	*ipa;char	*host;int     linenum;{	struct	hostent	*hp;	struct	netent	*np;	struct	in_addr	ip;	if (!strcasecmp("any", host))		return 0;#ifdef	USE_INET6	if (use_inet6) {		if (inet_pton(AF_INET6, host, ipa) == 1)			return 0;		else			return -1;	}#endif	if (isdigit(*host) && inet_aton(host, &ip)) {		*ipa = ip.s_addr;		return 0;	}	if (!strcasecmp("<thishost>", host))		host = thishost;	if (!(hp = gethostbyname(host))) {		if (!(np = getnetbyname(host))) {			fprintf(stderr, "%d: can't resolve hostname: %s\n",				linenum, host);			return -1;		}		*ipa = htonl(np->n_net);		return 0;	}	*ipa = *(u_32_t *)hp->h_addr;	return 0;}/* * check for possible presence of the port fields in the line */int	ports(seg, pp, cp, tp, linenum)char	***seg;u_short	*pp, *tp;int	*cp;int     linenum;{	int	comp = -1;	if (!*seg || !**seg || !***seg)		return 0;	if (!strcasecmp(**seg, "port") && *(*seg + 1) && *(*seg + 2)) {		(*seg)++;		if (isalnum(***seg) && *(*seg + 2)) {			if (portnum(**seg, pp, linenum) == 0)				return -1;			(*seg)++;			if (!strcmp(**seg, "<>"))				comp = FR_OUTRANGE;			else if (!strcmp(**seg, "><"))				comp = FR_INRANGE;			else {				fprintf(stderr,					"%d: unknown range operator (%s)\n",					linenum, **seg);				return -1;			}			(*seg)++;			if (**seg == NULL) {				fprintf(stderr, "%d: missing 2nd port value\n",					linenum);				return -1;			}			if (portnum(**seg, tp, linenum) == 0)				return -1;		} else if (!strcmp(**seg, "=") || !strcasecmp(**seg, "eq"))			comp = FR_EQUAL;		else if (!strcmp(**seg, "!=") || !strcasecmp(**seg, "ne"))			comp = FR_NEQUAL;		else if (!strcmp(**seg, "<") || !strcasecmp(**seg, "lt"))			comp = FR_LESST;		else if (!strcmp(**seg, ">") || !strcasecmp(**seg, "gt"))			comp = FR_GREATERT;		else if (!strcmp(**seg, "<=") || !strcasecmp(**seg, "le"))			comp = FR_LESSTE;		else if (!strcmp(**seg, ">=") || !strcasecmp(**seg, "ge"))			comp = FR_GREATERTE;		else {			fprintf(stderr, "%d: unknown comparator (%s)\n",					linenum, **seg);			return -1;		}		if (comp != FR_OUTRANGE && comp != FR_INRANGE) {			(*seg)++;			if (portnum(**seg, pp, linenum) == 0)				return -1;		}		*cp = comp;		(*seg)++;	}	return 0;}/* * find the port number given by the name, either from getservbyname() or * straight atoi(). Return 1 on success, 0 on failure */int	portnum(name, port, linenum)char	*name;u_short	*port;int     linenum;{	struct	servent	*sp, *sp2;	u_short	p1 = 0;	int i;	if (isdigit(*name)) {		if (ratoi(name, &i, 0, USHRT_MAX)) {			*port = (u_short)i;			return 1;		}		fprintf(stderr, "%d: unknown port \"%s\"\n", linenum, name);		return 0;	}	if (proto != NULL && strcasecmp(proto, "tcp/udp") != 0) {		sp = getservbyname(name, proto);		if (sp) {			*port = ntohs(sp->s_port);			return 1;		}		fprintf(stderr, "%d: unknown service \"%s\".\n", linenum, name);		return 0;	}	sp = getservbyname(name, "tcp");	if (sp)		p1 = sp->s_port;	sp2 = getservbyname(name, "udp");	if (!sp || !sp2) {		fprintf(stderr, "%d: unknown tcp/udp service \"%s\".\n",			linenum, name);		return 0;	}	if (p1 != sp2->s_port) {		fprintf(stderr, "%d: %s %d/tcp is a different port to ",			linenum, name, p1);		fprintf(stderr, "%d: %s %d/udp\n", linenum, name, sp->s_port);		return 0;	}	*port = ntohs(p1);	return 1;}u_char tcp_flags(flgs, mask, linenum)char *flgs;u_char *mask;int    linenum;{	u_char tcpf = 0, tcpfm = 0, *fp = &tcpf;	char *s, *t;	if (*flgs == '0') {		s = strchr(flgs, '/');		if (s)			*s++ = '\0';		tcpf = strtol(flgs, NULL, 0);		fp = &tcpfm;	} else		s = flgs;	for (; *s; s++) {		if (*s == '/' && fp == &tcpf) {			fp = &tcpfm;			if (*(s + 1) == '0')				break;			continue;		}		if (!(t = index(flagset, *s))) {			fprintf(stderr, "%d: unknown flag (%c)\n", linenum, *s);			return 0;		}		*fp |= flags[t - flagset];	}	if (s && *s == '0')		tcpfm = strtol(s, NULL, 0);	if (!tcpfm) {		if (tcpf == TH_SYN)			tcpfm = 0xff & ~(TH_ECN|TH_CWR);		else			tcpfm = 0xff & ~(TH_ECN);	}	*mask = tcpfm;	return tcpf;}/* * count consecutive 1's in bit mask.  If the mask generated by counting * consecutive 1's is different to that passed, return -1, else return # * of bits. */int	countbits(ip)u_32_t	ip;{	u_32_t	ipn;	int	cnt = 0, i, j;	ip = ipn = ntohl(ip);	for (i = 32; i; i--, ipn *= 2)		if (ipn & 0x80000000)			cnt++;		else			break;	ipn = 0;	for (i = 32, j = cnt; i; i--, j--) {		ipn *= 2;		if (j > 0)			ipn++;	}	if (ipn == ip)		return cnt;	return -1;}#ifdef	USE_INET6int count6bits(msk)u_32_t *msk;{	int i = 0, k;	u_32_t j;	for (k = 3; k >= 0; k--)		if (msk[k] == 0xffffffff)			i += 32;		else {			for (j = msk[k]; j; j <<= 1)				if (j & 0x80000000)					i++;		}	return i;}#endifchar	*portname(pr, port)int	pr, port;{	static	char	buf[32];	struct	protoent	*p = NULL;	struct	servent	*sv = NULL, *sv1 = NULL;	if (pr == -1) {		if ((sv = getservbyport(htons(port), "tcp"))) {			strncpy(buf, sv->s_name, sizeof(buf)-1);			buf[sizeof(buf)-1] = '\0';			sv1 = getservbyport(htons(port), "udp");			sv = strncasecmp(buf, sv->s_name, strlen(buf)) ?			     NULL : sv1;		}		if (sv)			return buf;	} else if (pr && (p = getprotobynumber(pr))) {		if ((sv = getservbyport(htons(port), p->p_name))) {			strncpy(buf, sv->s_name, sizeof(buf)-1);			buf[sizeof(buf)-1] = '\0';			return buf;		}	}	(void) sprintf(buf, "%d", port);	return buf;}int	ratoi(ps, pi, min, max)char 	*ps;int	*pi, min, max;{	int i;	char *pe;	i = (int)strtol(ps, &pe, 0);	if (*pe != '\0' || i < min || i > max)		return 0;	*pi = i;	return 1;}int	ratoui(ps, pi, min, max)char 	*ps;u_int	*pi, min, max;{	u_int i;	char *pe;	i = (u_int)strtol(ps, &pe, 0);	if (*pe != '\0' || i < min || i > max)		return 0;	*pi = i;	return 1;}void	printhostmask(v, addr, mask)int	v;u_32_t	*addr, *mask;{	struct in_addr ipa;	int ones;#ifdef USE_INET6	if (v == 6) {		ones = count6bits(mask);		if (ones == 0 && !addr[0] && !addr[1] && !addr[2] && !addr[3])			printf("any");		else {			char ipbuf[64];			printf("%s/%d",			       inet_ntop(AF_INET6, addr, ipbuf, sizeof(ipbuf)),			       ones);		}	}	else#endif	if (!*addr && !*mask)		printf("any");	else {		ipa.s_addr = *addr;		printf("%s", inet_ntoa(ipa));		if ((ones = countbits(*mask)) == -1) {			ipa.s_addr = *mask;			printf("/%s", inet_ntoa(ipa));		} else			printf("/%d", ones);	}}void	printportcmp(pr, frp)int	pr;frpcmp_t	*frp;{	static char *pcmp1[] = { "*", "=", "!=", "<", ">", "<=", ">=",				 "<>", "><"};	if (frp->frp_cmp == FR_INRANGE || frp->frp_cmp == FR_OUTRANGE)		printf(" port %d %s %d", frp->frp_port,			     pcmp1[frp->frp_cmp], frp->frp_top);	else		printf(" port %s %s", pcmp1[frp->frp_cmp],			     portname(pr, frp->frp_port));}void printbuf(buf, len, zend)char *buf;int len, zend;{	char *s, c;	int i;	for (s = buf, i = len; i; i--) {		c = *s++;		if (isprint(c))			putchar(c);		else			printf("\\%03o", c);		if ((c == '\0') && zend)			break;	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -