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

📄 firewall.c

📁 wm PNE 3.3 source code, running at more than vxworks6.x version.
💻 C
字号:
/* $Header: /usr/cvsroot/target/src/wrn/wm/demo/lib/firewall.c,v 1.4 2003/01/15 14:04:31 josh Exp $ *//* * Copyright (C) 1999-2005 Wind River Systems, Inc. * All rights reserved.  Provided under license only. * Distribution or other use of this software is only * permitted pursuant to the terms of a license agreement * from Wind River Systems (and is otherwise prohibited). * Refer to that license agreement for terms of use. *//**************************************************************************** *  Copyright 1998 Integrated Systems, Inc. *  All rights reserved. ****************************************************************************//* * Rudimentary firewall built on top of Attache. * This is a work in progress, I need the basic functionality to solve * a short term problem but the code will need more work to make * it as general as it should be. *//* * $Log: firewall.c,v $ * Revision 1.4  2003/01/15 14:04:31  josh * directory structure shifting * * Revision 1.3  2001/11/08 15:56:21  tneale * Updated for newest file layout * * Revision 1.2  2001/11/06 20:11:11  josh * updating include paths to include proper path to layout directory * * Revision 1.1.1.1  2001/11/05 17:48:41  tneale * Tornado shuffle * * Revision 2.4  2001/01/19 22:23:41  paul * Update copyright. * * Revision 2.3  2000/03/17 00:12:38  meister * Update copyright message * * Revision 2.2  1998/09/08 05:21:46  sra * Compiler warnings. * * Revision 2.1  1998/09/06 08:11:08  sra * Packet filtering hooks in Attache, rudimentary firewall * implementation in Snark. * *//* [clearcase]modification history-------------------01a,19apr05,job  update copyright notices*/#include <wrn/wm/common/config.h>#include <wrn/wm/common/glue.h>#include <wrn/wm/attache/config.h>#include <wrn/wm/attache/timer.h>#include <wrn/wm/attache/packet.h>#include <wrn/wm/attache/net.h>#include <wrn/wm/attache/route.h>#include <wrn/wm/attache/ip.h>#include <wrn/wm/attache/udp.h>#include <wrn/wm/attache/glue.h>#include <wrn/wm/util/layout/ip.h>#if INSTALL_ATTACHE_IPV6#include <wrn/wm/util/layout/ip6.h>#endif#include <wrn/wm/demo/snarklib.h>#include <wrn/wm/demo/read_ini.h>#include <wrn/wm/demo/parse.h>enum fw_action {  FW_ALLOW = 0,  FW_DROP  = 1,  FW_RESET = 2};struct filter {  struct filter *next;  enum fw_action action;  bits8_t proto, src_prefix, dst_prefix;  bits16_t src_low_port, src_high_port, dst_low_port, dst_high_port;  ipaddr_t src_addr, dst_addr;  char ifname[20];  unsigned negate_proto : 1;  unsigned negate_src_addr : 1;  unsigned negate_dst_addr : 1;  unsigned negate_src_port : 1;  unsigned negate_dst_port : 1;  unsigned negate_ifname : 1;  unsigned tcp_established : 1;  unsigned tcp_setup : 1;};enum filter_argv {  ARGV_ACTION,  ARGV_PROTO,  ARGV_SRC_ADDR,  ARGV_SRC_PORT,  ARGV_DST_ADDR,  ARGV_DST_PORT,  ARGV_IFNAME,  ARGV_MINLENGTH};enum fw_tcpflag {  TCPFLAG_ESTABLISHED,  TCPFLAG_SETUP,};static struct action_table {  char *name;  enum fw_action action;} action_table[] = {  { "allow", FW_ALLOW },  { "drop",  FW_DROP  },  { "reset", FW_RESET },};static struct tcpflag_table {  char *name;  enum fw_tcpflag flag;} tcpflag_table[] = {  { "established", TCPFLAG_ESTABLISHED },  { "setup",       TCPFLAG_SETUP       },};static struct proto_table {  char *name;  bits8_t proto;} proto_table[] = {  { "*",    0		        },  { "icmp", IP_PROTOCOL_is_ICMP },  { "tcp",  IP_PROTOCOL_is_TCP  },  { "udp",  IP_PROTOCOL_is_UDP  },};static struct filter *ifilter = 0;static struct filter *ofilter = 0;static struct filter *ffilter = 0;static struct keyword_table action_keywords, proto_keywords, tcpflag_keywords;#ifndef GET_TCP_HEADER_DESTINATION_PORT#define GET_TCP_HEADER_DESTINATION_PORT(_P_) \  GET_IP_PORT_NUMBER(PTR_TCP_HEADER_DESTINATION_PORT(_P_))#endif#ifndef GET_TCP_HEADER_SOURCE_PORT#define GET_TCP_HEADER_SOURCE_PORT(_P_) \  GET_IP_PORT_NUMBER(PTR_TCP_HEADER_SOURCE_PORT(_P_))#endif/* * Compare the first len bits of two ipaddr_ts, return nonzero if they match. */static int ipaddr_match (ipaddr_t *a1, ipaddr_t *a2, bits8_t len){  ipaddr_bits_t *b1, *b2;  BUG_ASSERT(a1 && a2 && len <= MAX_IP_ADDR_LEN * 8);  if (!len)    return 1;  if (GET_IPADDR_TYPE(a1) != GET_IPADDR_TYPE(a2))    return 0;  for (b1 = PTR_IPADDR_BITS(a1), b2 = PTR_IPADDR_BITS(a2);       len >= 8;       b1++, b2++, len -= 8)    if (*b1 != *b2)      return 0;  return !((*b1 ^ *b2) >> (8 - len));}#define FILTER_ALLOW() \  do { \    BUG_SUPPORT(ipaddr_to_string(&src_addr, src_host, sizeof(src_host))); \    BUG_SUPPORT(ipaddr_to_string(&dst_addr, dst_host, sizeof(dst_host))); \    BUG(BUG_SNARK_FIREWALL_ALLOW_PKT, BUG_CONTINUABLE, p, \	(BUG_OUT, "FW: Allow: %u %s %u %s %u %s", \	 proto, src_host, src_port, dst_host, dst_port, ifname)); \    return (int) FW_ALLOW; \  } while (0)#define FILTER_DROP() \  do { \    BUG_SUPPORT(ipaddr_to_string(&src_addr, src_host, sizeof(src_host))); \    BUG_SUPPORT(ipaddr_to_string(&dst_addr, dst_host, sizeof(dst_host))); \    BUG(BUG_SNARK_FIREWALL_DROP_PKT, BUG_CONTINUABLE, p, \	(BUG_OUT, "FW: Drop: %u %s %u %s %u %s", \	 proto, src_host, src_port, dst_host, dst_port, ifname)); \    return (int) FW_DROP; \  } while (0)#define FILTER_RESET() \  do { \    BUG_SUPPORT(ipaddr_to_string(&src_addr, src_host, sizeof(src_host))); \    BUG_SUPPORT(ipaddr_to_string(&dst_addr, dst_host, sizeof(dst_host))); \    BUG(BUG_SNARK_FIREWALL_RESET_PKT, BUG_CONTINUABLE, p, \	(BUG_OUT, "FW: Reset: %u %s %u %s %u %s", \	 proto, src_host, src_port, dst_host, dst_port, ifname)); \    return (int) FW_RESET; \  } while (0)static int filter(packet *p, struct filter *f, bits8_t *ip_hdr){  bits8_t proto = 0;  bits16_t src_port = 0, dst_port = 0;  ipaddr_t src_addr, dst_addr;  char *ifname = "";  bits8_t *tp_hdr = 0;  int tcp_established = 0, tcp_setup = 0;  size_t optlen;  BUG_SUPPORT(char src_host[MAX_IPADDR_STRING_LEN]);  BUG_SUPPORT(char dst_host[MAX_IPADDR_STRING_LEN]);  BUG_ASSERT(p && ip_hdr);  /*   * Extract relevant fields from the packet.   */  switch (GET_IP_HEADER_VERSION(ip_hdr)) {#if INSTALL_ATTACHE_IPV4  case IP_HEADER_VERSION_is_IPV4:    optlen = GET_IP_HEADER_HEADER_LENGTH(ip_hdr) * 4 - SIZEOF_IP_HEADER;    tp_hdr = ip_hdr + SIZEOF_IP_HEADER + optlen;    break;#endif /* INSTALL_ATTACHE_IPV4 */#if INSTALL_ATTACHE_IPV6  case IP_HEADER_VERSION_is_IPV6:    /* This isn't right. */    optlen = 0;    tp_hdr = ip_hdr + SIZEOF_IP6_HEADER + optlen;    break;#endif /* INSTALL_ATTACHE_IPV6 */  default:    FILTER_DROP();  }  /* For the moment, just drop any packets containing IP options. */  if (optlen)    FILTER_DROP();  proto = GET_IP_HEADER_PROTOCOL(ip_hdr);  GET_IP_SRC_ADDR(ip_hdr, &src_addr);  GET_IP_DST_ADDR(ip_hdr, &dst_addr);  switch (proto) {  case IP_PROTOCOL_is_TCP:    if (p->pkt_data + p->pkt_datalen < tp_hdr + SIZEOF_TCP_HEADER)      FILTER_DROP();    src_port = GET_TCP_HEADER_SOURCE_PORT(tp_hdr);    dst_port = GET_TCP_HEADER_DESTINATION_PORT(tp_hdr);    tcp_established = GET_TCP_HEADER_ACK(tp_hdr) || GET_TCP_HEADER_RST(tp_hdr);    tcp_setup = GET_TCP_HEADER_SYN(tp_hdr) && !GET_TCP_HEADER_ACK(tp_hdr);    break;  case IP_PROTOCOL_is_UDP:    if (p->pkt_data + p->pkt_datalen < tp_hdr + SIZEOF_UDP_HEADER)      FILTER_DROP();    src_port = GET_UDP_HEADER_SOURCE_PORT(tp_hdr);    dst_port = GET_UDP_HEADER_DESTINATION_PORT(tp_hdr);    break;  default:    src_port = dst_port = 0;  }  ifname = (p->pkt_n && p->pkt_n->s_name) ? p->pkt_n->s_name : "";  /*   * Look for a matching rule.   */  while (f &&	 ((f->proto && (f->negate_proto ^ (proto != f->proto))) ||	  (proto == IP_PROTOCOL_is_TCP && ((f->tcp_setup && !tcp_setup) || (f->tcp_established && !tcp_established))) ||	  (f->negate_src_port ^ (src_port < f->src_low_port || src_port > f->src_high_port)) ||	  (f->negate_dst_port ^ (dst_port < f->dst_low_port || dst_port > f->dst_high_port)) ||	  (f->negate_src_addr ^ !ipaddr_match(&src_addr, &f->src_addr, f->src_prefix)) ||	  (f->negate_dst_addr ^ !ipaddr_match(&dst_addr, &f->dst_addr, f->dst_prefix)) ||	  (*f->ifname && (f->negate_ifname ^ (STRCMP(ifname, f->ifname) != 0)))))    f = f->next;  /*   * If we found a rule, apply it.   */  if (f) {    switch (f->action) {    case FW_ALLOW:      FILTER_ALLOW();    case FW_RESET:#if 0      /*       * p->pkt_data would need adjustment here       */      tcp_clrs(p);#endif      FILTER_RESET();    case FW_DROP:      FILTER_DROP();    }  }  /*   * For now, if we didn't find a matching rule, silently drop the packet.   */  FILTER_DROP();}int snark_firewall_inbound_filter(packet *p){  return filter(p, ifilter, PKT_GET_IP_HEADER(p));}int snark_firewall_outbound_filter(packet *p){  return filter(p, ofilter, p->pkt_data);}int snark_firewall_forward_filter(packet *p){  return filter(p, ffilter, p->pkt_data);}  static int parse_action(struct filter *rule, char **av){  struct action_table *entry;  if (!(entry = keyword_find(&action_keywords, av[ARGV_ACTION])))    return 0;  rule->action = entry->action;  return 1;}static int parse_proto(struct filter *rule, char **av){  struct proto_table *entry;  char *sep;  if (*av[ARGV_PROTO] == '!') {    rule->negate_proto = 1;    av[ARGV_PROTO]++;  }  if ((entry = keyword_find(&proto_keywords, av[ARGV_PROTO])) != 0) {    rule->proto = entry->proto;    return 1;  }  rule->proto = STRTOUL(av[ARGV_PROTO], &sep, 10);  return av[ARGV_PROTO] != '\0' && *sep == '\0';}static int parse_ipaddr(struct filter *rule, char **av, int ai){  ipaddr_t *addr;  bits8_t *prefix;  unsigned negate = 0;  char *pfx;  if (*av[ai] == '!') {    negate = 1;    av[ai]++;  }  switch (ai) {  case ARGV_SRC_ADDR:    rule->negate_src_addr = negate;    addr = &rule->src_addr;    prefix = &rule->src_prefix;    break;  case ARGV_DST_ADDR:    rule->negate_dst_addr = negate;    addr = &rule->dst_addr;    prefix = &rule->dst_prefix;    break;  default:    return 0;  }  if (av[ai][0] == '*' && av[ai][1] == '\0') {    *prefix = 0;    SET_IPADDR_TYPE(addr, IPNONE);    return 1;  }  for (pfx = av[ai]; *pfx != '\0'; ++pfx) {    if (*pfx == '/') {      *pfx++ = '\0';      if (*pfx == '\0')	return 0;      break;    }  }  string_to_ipaddr(av[ai], addr);  if (GET_IPADDR_TYPE(addr) == IPNONE)    return 0;  if (*pfx == '\0') {    *prefix = IPADDR_LENGTH(addr) * 8;    return 1;  } else {    *prefix = STRTOUL(pfx, &pfx, 10);    return *pfx == '\0' && *prefix <= IPADDR_LENGTH(addr) * 8;  }}static int parse_port(struct filter *rule, char **av, int ai){  bits16_t *lowport, *highport;  unsigned negate = 0;  char *sep;  if (*av[ai] == '!') {    negate = 1;    av[ai]++;  }  switch (ai) {  case ARGV_SRC_PORT:    rule->negate_src_port = negate;    lowport = &rule->src_low_port;    highport = &rule->src_high_port;    break;  case ARGV_DST_PORT:    rule->negate_dst_port = negate;    lowport = &rule->dst_low_port;    highport = &rule->dst_high_port;    break;  default:    return 0;  }  switch (av[ai][0]) {  case '\0':    return 0;  case '*':    if (av[ai][1] != '\0')      return 0;    *lowport = 0;    *highport = 0xFFFF;    return 1;  }  *lowport = STRTOUL(av[ai], &sep, 10);  switch (*sep) {  case '\0':    *highport = *lowport;    return 1;  case '-':    if (*++sep == '\0')      return 0;    *highport = STRTOUL(sep, &sep, 10);    return *sep == '\0';  default:    return 0;  }}static int parse_ifname(struct filter *rule, char **av){  if (*av[ARGV_IFNAME] == '!') {    rule->negate_ifname = 1;    av[ARGV_IFNAME]++;  }  if (*av[ARGV_IFNAME] == '*' && *++av[ARGV_IFNAME] != '\0')    return 0;  strncpy(rule->ifname, av[ARGV_IFNAME], sizeof(rule->ifname) - 1);  return 1;}static int parse_tcpflag(struct filter *rule, char **av, int ac){  struct tcpflag_table *entry;  if (rule->proto != IP_PROTOCOL_is_TCP || ac == ARGV_MINLENGTH)    return 1;  if (ac > ARGV_MINLENGTH + 1 || (entry = keyword_find(&tcpflag_keywords, av[ARGV_MINLENGTH])) == 0)    return 0;  switch (entry->flag) {  case TCPFLAG_ESTABLISHED:    rule->tcp_established = 1;    return 1;  case TCPFLAG_SETUP:    rule->tcp_setup = 1;    return 1;  default:    return 0;  }}static void config_1 (struct ini_handle *ini_handle, char *name, struct filter **tail){  static char snark_section[] = "etc snark firewall";  struct filter *rule = 0;  char *s, buf[256], *av[20];  int ac;  BUG_ASSERT(sizeof(buf) >= ini_handle->buflen);  *tail = 0;  for (s = ini_iter_start(ini_handle, snark_section, name); s;       s = ini_iter_next(ini_handle)) {    if (!rule && !(rule = GLUE_ALLOC(sizeof(*rule)))) {      BUG(BUG_SNARK_FIREWALL_CONFIG_ALLOC_FAILED, BUG_FATAL, s,	  (BUG_OUT, "fw_config_1(): allocation failed for rule: %s", s));      return;    }    MEMSET(rule, 0, sizeof(*rule));    STRCPY(buf, s);    if ((ac = parse_line(buf, av, sizeof(av)/sizeof(*av))) < ARGV_MINLENGTH ||	!parse_action(rule, av) ||	!parse_proto(rule, av) ||	!parse_ipaddr(rule, av, ARGV_SRC_ADDR) ||	!parse_ipaddr(rule, av, ARGV_DST_ADDR) ||	!parse_port(rule, av, ARGV_SRC_PORT) ||	!parse_port(rule, av, ARGV_DST_PORT) ||	!parse_ifname(rule, av) ||	!parse_tcpflag(rule, av, ac)) {      BUG(BUG_SNARK_FIREWALL_CONFIG_PARSE_ERROR, BUG_FATAL, s,	  (BUG_OUT, "fw_config_1(): couldn't parse rule: %s", s));      GLUE_FREE(rule);      return;    }    *tail = rule;    tail = &rule->next;    rule = 0;  }}void snark_firewall_init (void){  struct ini_handle *ini_handle = ini_open(256);  KEYWORD_INIT(&action_keywords, action_table);  KEYWORD_INIT(&proto_keywords, proto_table);  KEYWORD_INIT(&tcpflag_keywords, tcpflag_table);  config_1(ini_handle, "inbound-filter", &ifilter);  config_1(ini_handle, "outbound-filter", &ofilter);  config_1(ini_handle, "forward-filter", &ffilter);  ini_close(ini_handle);}

⌨️ 快捷键说明

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