1
0
mirror of https://github.com/nmap/nmap.git synced 2026-01-24 07:09:01 +00:00
Files
nmap/libdnet-stripped/src/fw-ipchains.c

228 lines
5.6 KiB
C

/*
* fw-ipchains.c
*
* Copyright (c) 2001 Dug Song <dugsong@monkey.org>
*
* $Id: fw-ipchains.c,v 1.8 2004/05/05 21:25:20 dugsong Exp $
*/
#include "config.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#undef __USE_BSD
#include <netinet/ip_icmp.h>
#include <linux/if.h>
#ifdef HAVE_LINUX_IP_FW_H
#include <linux/ip_fw.h>
#elif defined(HAVE_LINUX_IP_FWCHAINS_H)
#include <linux/ip_fwchains.h>
#elif defined(HAVE_LINUX_NETFILTER_IPV4_IPCHAINS_CORE_H)
#include <linux/netfilter_ipv4/ipchains_core.h>
#endif
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "dnet.h"
#define PROC_IPCHAINS_FILE "/proc/net/ip_fwchains"
struct fw_handle {
int fd;
};
static void
fr_to_fwc(const struct fw_rule *fr, struct ip_fwchange *fwc)
{
memset(fwc, 0, sizeof(*fwc));
strlcpy(fwc->fwc_rule.ipfw.fw_vianame, fr->fw_device, IFNAMSIZ);
if (fr->fw_op == FW_OP_ALLOW)
strlcpy(fwc->fwc_rule.label, IP_FW_LABEL_ACCEPT,
sizeof(fwc->fwc_rule.label));
else
strlcpy(fwc->fwc_rule.label, IP_FW_LABEL_BLOCK,
sizeof(fwc->fwc_rule.label));
if (fr->fw_dir == FW_DIR_IN)
strlcpy(fwc->fwc_label, IP_FW_LABEL_INPUT,
sizeof(fwc->fwc_label));
else
strlcpy(fwc->fwc_label, IP_FW_LABEL_OUTPUT,
sizeof(fwc->fwc_label));
fwc->fwc_rule.ipfw.fw_proto = fr->fw_proto;
fwc->fwc_rule.ipfw.fw_src.s_addr = fr->fw_src.addr_ip;
fwc->fwc_rule.ipfw.fw_dst.s_addr = fr->fw_dst.addr_ip;
addr_btom(fr->fw_src.addr_bits, &fwc->fwc_rule.ipfw.fw_smsk.s_addr,
IP_ADDR_LEN);
addr_btom(fr->fw_dst.addr_bits, &fwc->fwc_rule.ipfw.fw_dmsk.s_addr,
IP_ADDR_LEN);
/* XXX - ICMP? */
fwc->fwc_rule.ipfw.fw_spts[0] = fr->fw_sport[0];
fwc->fwc_rule.ipfw.fw_spts[1] = fr->fw_sport[1];
fwc->fwc_rule.ipfw.fw_dpts[0] = fr->fw_dport[0];
fwc->fwc_rule.ipfw.fw_dpts[1] = fr->fw_dport[1];
}
static void
fwc_to_fr(const struct ip_fwchange *fwc, struct fw_rule *fr)
{
memset(fr, 0, sizeof(*fr));
strlcpy(fr->fw_device, fwc->fwc_rule.ipfw.fw_vianame,
sizeof(fr->fw_device));
if (strcmp(fwc->fwc_rule.label, IP_FW_LABEL_ACCEPT) == 0)
fr->fw_op = FW_OP_ALLOW;
else
fr->fw_op = FW_OP_BLOCK;
if (strcmp(fwc->fwc_label, IP_FW_LABEL_INPUT) == 0)
fr->fw_dir = FW_DIR_IN;
else
fr->fw_dir = FW_DIR_OUT;
fr->fw_proto = fwc->fwc_rule.ipfw.fw_proto;
fr->fw_src.addr_type = fr->fw_dst.addr_type = ADDR_TYPE_IP;
fr->fw_src.addr_ip = fwc->fwc_rule.ipfw.fw_src.s_addr;
fr->fw_dst.addr_ip = fwc->fwc_rule.ipfw.fw_dst.s_addr;
addr_mtob(&fwc->fwc_rule.ipfw.fw_smsk.s_addr, IP_ADDR_LEN,
&fr->fw_src.addr_bits);
addr_mtob(&fwc->fwc_rule.ipfw.fw_dmsk.s_addr, IP_ADDR_LEN,
&fr->fw_dst.addr_bits);
/* XXX - ICMP? */
fr->fw_sport[0] = fwc->fwc_rule.ipfw.fw_spts[0];
fr->fw_sport[1] = fwc->fwc_rule.ipfw.fw_spts[1];
fr->fw_dport[0] = fwc->fwc_rule.ipfw.fw_dpts[0];
fr->fw_dport[1] = fwc->fwc_rule.ipfw.fw_dpts[1];
}
fw_t *
fw_open(void)
{
fw_t *fw;
if ((fw = calloc(1, sizeof(*fw))) != NULL) {
if ((fw->fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
return (fw_close(fw));
}
return (fw);
}
int
fw_add(fw_t *fw, const struct fw_rule *rule)
{
struct ip_fwchange fwc;
fr_to_fwc(rule, &fwc);
return (setsockopt(fw->fd, IPPROTO_IP, IP_FW_APPEND,
&fwc, sizeof(fwc)));
}
int
fw_delete(fw_t *fw, const struct fw_rule *rule)
{
struct ip_fwchange fwc;
fr_to_fwc(rule, &fwc);
return (setsockopt(fw->fd, IPPROTO_IP, IP_FW_DELETE,
&fwc, sizeof(fwc)));
}
int
fw_loop(fw_t *fw, fw_handler callback, void *arg)
{
FILE *fp;
struct ip_fwchange fwc;
struct fw_rule fr;
char buf[BUFSIZ];
u_int phi, plo, bhi, blo, tand, txor;
int ret;
if ((fp = fopen(PROC_IPCHAINS_FILE, "r")) == NULL)
return (-1);
while (fgets(buf, sizeof(buf), fp) != NULL) {
if (sscanf(buf,
"%8s %X/%X->%X/%X %s %hX %hX %hu %u %u %u %u "
"%hu-%hu %hu-%hu A%X X%X %hX %u %hu %s\n",
fwc.fwc_label,
&fwc.fwc_rule.ipfw.fw_src.s_addr,
&fwc.fwc_rule.ipfw.fw_smsk.s_addr,
&fwc.fwc_rule.ipfw.fw_dst.s_addr,
&fwc.fwc_rule.ipfw.fw_dmsk.s_addr,
fwc.fwc_rule.ipfw.fw_vianame,
&fwc.fwc_rule.ipfw.fw_flg,
&fwc.fwc_rule.ipfw.fw_invflg,
&fwc.fwc_rule.ipfw.fw_proto,
&phi, &plo, &bhi, &blo,
&fwc.fwc_rule.ipfw.fw_spts[0],
&fwc.fwc_rule.ipfw.fw_spts[1],
&fwc.fwc_rule.ipfw.fw_dpts[0],
&fwc.fwc_rule.ipfw.fw_dpts[1],
&tand, &txor,
&fwc.fwc_rule.ipfw.fw_redirpt,
&fwc.fwc_rule.ipfw.fw_mark,
&fwc.fwc_rule.ipfw.fw_outputsize,
fwc.fwc_rule.label) != 23)
break;
if (strcmp(fwc.fwc_rule.label, IP_FW_LABEL_ACCEPT) != 0 &&
strcmp(fwc.fwc_rule.label, IP_FW_LABEL_BLOCK) != 0 &&
strcmp(fwc.fwc_rule.label, IP_FW_LABEL_REJECT) != 0)
continue;
if (strcmp(fwc.fwc_label, IP_FW_LABEL_INPUT) != 0 &&
strcmp(fwc.fwc_label, IP_FW_LABEL_OUTPUT) != 0)
continue;
if (strcmp(fwc.fwc_rule.label, "-") == 0)
(fwc.fwc_rule.label)[0] = '\0';
if (strcmp(fwc.fwc_rule.ipfw.fw_vianame, "-") == 0)
(fwc.fwc_rule.ipfw.fw_vianame)[0] = '\0';
fwc.fwc_rule.ipfw.fw_src.s_addr =
htonl(fwc.fwc_rule.ipfw.fw_src.s_addr);
fwc.fwc_rule.ipfw.fw_dst.s_addr =
htonl(fwc.fwc_rule.ipfw.fw_dst.s_addr);
fwc.fwc_rule.ipfw.fw_smsk.s_addr =
htonl(fwc.fwc_rule.ipfw.fw_smsk.s_addr);
fwc.fwc_rule.ipfw.fw_dmsk.s_addr =
htonl(fwc.fwc_rule.ipfw.fw_dmsk.s_addr);
fwc_to_fr(&fwc, &fr);
if ((ret = callback(&fr, arg)) != 0) {
fclose(fp);
return (ret);
}
}
fclose(fp);
return (0);
}
fw_t *
fw_close(fw_t *fw)
{
if (fw != NULL) {
if (fw->fd >= 0)
close(fw->fd);
free(fw);
}
return (NULL);
}