Ejemplo n.º 1
0
/* Performance critical - called for every packet */
static inline bool
ip6_packet_match(const struct sk_buff *skb,
		 const char *indev,
		 const char *outdev,
		 const struct ip6t_ip6 *ip6info,
		 unsigned int *protoff,
		 int *fragoff, bool *hotdrop)
{
	unsigned long ret;
	const struct ipv6hdr *ipv6 = ipv6_hdr(skb);

	if (NF_INVF(ip6info, IP6T_INV_SRCIP,
		    ipv6_masked_addr_cmp(&ipv6->saddr, &ip6info->smsk,
					 &ip6info->src)) ||
	    NF_INVF(ip6info, IP6T_INV_DSTIP,
		    ipv6_masked_addr_cmp(&ipv6->daddr, &ip6info->dmsk,
					 &ip6info->dst)))
		return false;

	ret = ifname_compare_aligned(indev, ip6info->iniface, ip6info->iniface_mask);

	if (NF_INVF(ip6info, IP6T_INV_VIA_IN, ret != 0))
		return false;

	ret = ifname_compare_aligned(outdev, ip6info->outiface, ip6info->outiface_mask);

	if (NF_INVF(ip6info, IP6T_INV_VIA_OUT, ret != 0))
		return false;

/* ... might want to do something with class and flowlabel here ... */

	/* look for the desired protocol header */
	if (ip6info->flags & IP6T_F_PROTO) {
		int protohdr;
		unsigned short _frag_off;

		protohdr = ipv6_find_hdr(skb, protoff, -1, &_frag_off, NULL);
		if (protohdr < 0) {
			if (_frag_off == 0)
				*hotdrop = true;
			return false;
		}
		*fragoff = _frag_off;

		if (ip6info->proto == protohdr) {
			if (ip6info->invflags & IP6T_INV_PROTO)
				return false;

			return true;
		}

		/* We need match for the '-p all', too! */
		if ((ip6info->proto != 0) &&
			!(ip6info->invflags & IP6T_INV_PROTO))
			return false;
	}
	return true;
}
Ejemplo n.º 2
0
static bool
ebt_stp_mt(const struct sk_buff *skb, struct xt_action_param *par)
{
	const struct ebt_stp_info *info = par->matchinfo;
	const struct stp_header *sp;
	struct stp_header _stph;
	const u8 header[6] = {0x42, 0x42, 0x03, 0x00, 0x00, 0x00};

	sp = skb_header_pointer(skb, 0, sizeof(_stph), &_stph);
	if (sp == NULL)
		return false;

	/* The stp code only considers these */
	if (memcmp(sp, header, sizeof(header)))
		return false;

	if ((info->bitmask & EBT_STP_TYPE) &&
	    NF_INVF(info, EBT_STP_TYPE, info->type != sp->type))
		return false;

	if (sp->type == BPDU_TYPE_CONFIG &&
	    info->bitmask & EBT_STP_CONFIG_MASK) {
		const struct stp_config_pdu *st;
		struct stp_config_pdu _stpc;

		st = skb_header_pointer(skb, sizeof(_stph),
					sizeof(_stpc), &_stpc);
		if (st == NULL)
			return false;
		return ebt_filter_config(info, st);
	}
	return true;
}
Ejemplo n.º 3
0
/* Performance critical - called for every packet */
static inline bool
ip_packet_match(const struct iphdr *ip,
		const char *indev,
		const char *outdev,
		const struct ipt_ip *ipinfo,
		int isfrag)
{
	unsigned long ret;

	if (NF_INVF(ipinfo, IPT_INV_SRCIP,
		    (ip->saddr & ipinfo->smsk.s_addr) != ipinfo->src.s_addr) ||
	    NF_INVF(ipinfo, IPT_INV_DSTIP,
		    (ip->daddr & ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr))
		return false;

	ret = ifname_compare_aligned(indev, ipinfo->iniface, ipinfo->iniface_mask);

	if (NF_INVF(ipinfo, IPT_INV_VIA_IN, ret != 0))
		return false;

	ret = ifname_compare_aligned(outdev, ipinfo->outiface, ipinfo->outiface_mask);

	if (NF_INVF(ipinfo, IPT_INV_VIA_OUT, ret != 0))
		return false;

	/* Check specific protocol */
	if (ipinfo->proto &&
	    NF_INVF(ipinfo, IPT_INV_PROTO, ip->protocol != ipinfo->proto))
		return false;

	/* If we have a fragment rule but the packet is not a fragment
	 * then we return zero */
	if (NF_INVF(ipinfo, IPT_INV_FRAG,
		    (ipinfo->flags & IPT_F_FRAG) && !isfrag))
		return false;

	return true;
}
Ejemplo n.º 4
0
static bool ebt_filter_config(const struct ebt_stp_info *info,
			      const struct stp_config_pdu *stpc)
{
	const struct ebt_stp_config_info *c;
	u16 v16;
	u32 v32;

	c = &info->config;
	if ((info->bitmask & EBT_STP_FLAGS) &&
	    NF_INVF(info, EBT_STP_FLAGS, c->flags != stpc->flags))
		return false;
	if (info->bitmask & EBT_STP_ROOTPRIO) {
		v16 = NR16(stpc->root);
		if (NF_INVF(info, EBT_STP_ROOTPRIO,
			    v16 < c->root_priol || v16 > c->root_priou))
			return false;
	}
	if (info->bitmask & EBT_STP_ROOTADDR) {
		if (NF_INVF(info, EBT_STP_ROOTADDR,
			    !ether_addr_equal_masked(&stpc->root[2],
						     c->root_addr,
						     c->root_addrmsk)))
			return false;
	}
	if (info->bitmask & EBT_STP_ROOTCOST) {
		v32 = NR32(stpc->root_cost);
		if (NF_INVF(info, EBT_STP_ROOTCOST,
			    v32 < c->root_costl || v32 > c->root_costu))
			return false;
	}
	if (info->bitmask & EBT_STP_SENDERPRIO) {
		v16 = NR16(stpc->sender);
		if (NF_INVF(info, EBT_STP_SENDERPRIO,
			    v16 < c->sender_priol || v16 > c->sender_priou))
			return false;
	}
	if (info->bitmask & EBT_STP_SENDERADDR) {
		if (NF_INVF(info, EBT_STP_SENDERADDR,
			    !ether_addr_equal_masked(&stpc->sender[2],
						     c->sender_addr,
						     c->sender_addrmsk)))
			return false;
	}
	if (info->bitmask & EBT_STP_PORT) {
		v16 = NR16(stpc->port);
		if (NF_INVF(info, EBT_STP_PORT,
			    v16 < c->portl || v16 > c->portu))
			return false;
	}
	if (info->bitmask & EBT_STP_MSGAGE) {
		v16 = NR16(stpc->msg_age);
		if (NF_INVF(info, EBT_STP_MSGAGE,
			    v16 < c->msg_agel || v16 > c->msg_ageu))
			return false;
	}
	if (info->bitmask & EBT_STP_MAXAGE) {
		v16 = NR16(stpc->max_age);
		if (NF_INVF(info, EBT_STP_MAXAGE,
			    v16 < c->max_agel || v16 > c->max_ageu))
			return false;
	}
	if (info->bitmask & EBT_STP_HELLOTIME) {
		v16 = NR16(stpc->hello_time);
		if (NF_INVF(info, EBT_STP_HELLOTIME,
			    v16 < c->hello_timel || v16 > c->hello_timeu))
			return false;
	}
	if (info->bitmask & EBT_STP_FWDD) {
		v16 = NR16(stpc->forward_delay);
		if (NF_INVF(info, EBT_STP_FWDD,
			    v16 < c->forward_delayl || v16 > c->forward_delayu))
			return false;
	}
	return true;
}
Ejemplo n.º 5
0
static bool
ebt_ip_mt(const struct sk_buff *skb, struct xt_action_param *par)
{
	const struct ebt_ip_info *info = par->matchinfo;
	const struct iphdr *ih;
	struct iphdr _iph;
	const union pkthdr *pptr;
	union pkthdr _pkthdr;

	ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
	if (ih == NULL)
		return false;
	if ((info->bitmask & EBT_IP_TOS) &&
	    NF_INVF(info, EBT_IP_TOS, info->tos != ih->tos))
		return false;
	if ((info->bitmask & EBT_IP_SOURCE) &&
	    NF_INVF(info, EBT_IP_SOURCE,
		    (ih->saddr & info->smsk) != info->saddr))
		return false;
	if ((info->bitmask & EBT_IP_DEST) &&
	    NF_INVF(info, EBT_IP_DEST,
		    (ih->daddr & info->dmsk) != info->daddr))
		return false;
	if (info->bitmask & EBT_IP_PROTO) {
		if (NF_INVF(info, EBT_IP_PROTO, info->protocol != ih->protocol))
			return false;
		if (!(info->bitmask & (EBT_IP_DPORT | EBT_IP_SPORT |
				       EBT_IP_ICMP | EBT_IP_IGMP)))
			return true;
		if (ntohs(ih->frag_off) & IP_OFFSET)
			return false;

		/* min icmp/igmp headersize is 4, so sizeof(_pkthdr) is ok. */
		pptr = skb_header_pointer(skb, ih->ihl*4,
					  sizeof(_pkthdr), &_pkthdr);
		if (pptr == NULL)
			return false;
		if (info->bitmask & EBT_IP_DPORT) {
			u32 dst = ntohs(pptr->tcpudphdr.dst);
			if (NF_INVF(info, EBT_IP_DPORT,
				    dst < info->dport[0] ||
				    dst > info->dport[1]))
				return false;
		}
		if (info->bitmask & EBT_IP_SPORT) {
			u32 src = ntohs(pptr->tcpudphdr.src);
			if (NF_INVF(info, EBT_IP_SPORT,
				    src < info->sport[0] ||
				    src > info->sport[1]))
				return false;
		}
		if ((info->bitmask & EBT_IP_ICMP) &&
		    NF_INVF(info, EBT_IP_ICMP,
			    pptr->icmphdr.type < info->icmp_type[0] ||
			    pptr->icmphdr.type > info->icmp_type[1] ||
			    pptr->icmphdr.code < info->icmp_code[0] ||
			    pptr->icmphdr.code > info->icmp_code[1]))
			return false;
		if ((info->bitmask & EBT_IP_IGMP) &&
		    NF_INVF(info, EBT_IP_IGMP,
			    pptr->igmphdr.type < info->igmp_type[0] ||
			    pptr->igmphdr.type > info->igmp_type[1]))
			return false;
	}
	return true;
}
Ejemplo n.º 6
0
/* Returns whether packet matches rule or not. */
static inline int arp_packet_match(const struct arphdr *arphdr,
				   struct net_device *dev,
				   const char *indev,
				   const char *outdev,
				   const struct arpt_arp *arpinfo)
{
	const char *arpptr = (char *)(arphdr + 1);
	const char *src_devaddr, *tgt_devaddr;
	__be32 src_ipaddr, tgt_ipaddr;
	long ret;

	if (NF_INVF(arpinfo, ARPT_INV_ARPOP,
		    (arphdr->ar_op & arpinfo->arpop_mask) != arpinfo->arpop))
		return 0;

	if (NF_INVF(arpinfo, ARPT_INV_ARPHRD,
		    (arphdr->ar_hrd & arpinfo->arhrd_mask) != arpinfo->arhrd))
		return 0;

	if (NF_INVF(arpinfo, ARPT_INV_ARPPRO,
		    (arphdr->ar_pro & arpinfo->arpro_mask) != arpinfo->arpro))
		return 0;

	if (NF_INVF(arpinfo, ARPT_INV_ARPHLN,
		    (arphdr->ar_hln & arpinfo->arhln_mask) != arpinfo->arhln))
		return 0;

	src_devaddr = arpptr;
	arpptr += dev->addr_len;
	memcpy(&src_ipaddr, arpptr, sizeof(u32));
	arpptr += sizeof(u32);
	tgt_devaddr = arpptr;
	arpptr += dev->addr_len;
	memcpy(&tgt_ipaddr, arpptr, sizeof(u32));

	if (NF_INVF(arpinfo, ARPT_INV_SRCDEVADDR,
		    arp_devaddr_compare(&arpinfo->src_devaddr, src_devaddr,
					dev->addr_len)) ||
	    NF_INVF(arpinfo, ARPT_INV_TGTDEVADDR,
		    arp_devaddr_compare(&arpinfo->tgt_devaddr, tgt_devaddr,
					dev->addr_len)))
		return 0;

	if (NF_INVF(arpinfo, ARPT_INV_SRCIP,
		    (src_ipaddr & arpinfo->smsk.s_addr) != arpinfo->src.s_addr) ||
	    NF_INVF(arpinfo, ARPT_INV_TGTIP,
		    (tgt_ipaddr & arpinfo->tmsk.s_addr) != arpinfo->tgt.s_addr))
		return 0;

	/* Look for ifname matches.  */
	ret = ifname_compare(indev, arpinfo->iniface, arpinfo->iniface_mask);

	if (NF_INVF(arpinfo, ARPT_INV_VIA_IN, ret != 0))
		return 0;

	ret = ifname_compare(outdev, arpinfo->outiface, arpinfo->outiface_mask);

	if (NF_INVF(arpinfo, ARPT_INV_VIA_OUT, ret != 0))
		return 0;

	return 1;
}
Ejemplo n.º 7
0
static bool
ebt_ip6_mt(const struct sk_buff *skb, struct xt_action_param *par)
{
	const struct ebt_ip6_info *info = par->matchinfo;
	const struct ipv6hdr *ih6;
	struct ipv6hdr _ip6h;
	const union pkthdr *pptr;
	union pkthdr _pkthdr;

	ih6 = skb_header_pointer(skb, 0, sizeof(_ip6h), &_ip6h);
	if (ih6 == NULL)
		return false;
	if ((info->bitmask & EBT_IP6_TCLASS) &&
	    NF_INVF(info, EBT_IP6_TCLASS,
		    info->tclass != ipv6_get_dsfield(ih6)))
		return false;
	if (((info->bitmask & EBT_IP6_SOURCE) &&
	     NF_INVF(info, EBT_IP6_SOURCE,
		     ipv6_masked_addr_cmp(&ih6->saddr, &info->smsk,
					  &info->saddr))) ||
	    ((info->bitmask & EBT_IP6_DEST) &&
	     NF_INVF(info, EBT_IP6_DEST,
		     ipv6_masked_addr_cmp(&ih6->daddr, &info->dmsk,
					  &info->daddr))))
		return false;
	if (info->bitmask & EBT_IP6_PROTO) {
		uint8_t nexthdr = ih6->nexthdr;
		__be16 frag_off;
		int offset_ph;

		offset_ph = ipv6_skip_exthdr(skb, sizeof(_ip6h), &nexthdr, &frag_off);
		if (offset_ph == -1)
			return false;
		if (NF_INVF(info, EBT_IP6_PROTO, info->protocol != nexthdr))
			return false;
		if (!(info->bitmask & (EBT_IP6_DPORT |
				       EBT_IP6_SPORT | EBT_IP6_ICMP6)))
			return true;

		/* min icmpv6 headersize is 4, so sizeof(_pkthdr) is ok. */
		pptr = skb_header_pointer(skb, offset_ph, sizeof(_pkthdr),
					  &_pkthdr);
		if (pptr == NULL)
			return false;
		if (info->bitmask & EBT_IP6_DPORT) {
			u16 dst = ntohs(pptr->tcpudphdr.dst);
			if (NF_INVF(info, EBT_IP6_DPORT,
				    dst < info->dport[0] ||
				    dst > info->dport[1]))
				return false;
		}
		if (info->bitmask & EBT_IP6_SPORT) {
			u16 src = ntohs(pptr->tcpudphdr.src);
			if (NF_INVF(info, EBT_IP6_SPORT,
				    src < info->sport[0] ||
				    src > info->sport[1]))
				return false;
		}
		if ((info->bitmask & EBT_IP6_ICMP6) &&
		    NF_INVF(info, EBT_IP6_ICMP6,
			    pptr->icmphdr.type < info->icmpv6_type[0] ||
			    pptr->icmphdr.type > info->icmpv6_type[1] ||
			    pptr->icmphdr.code < info->icmpv6_code[0] ||
			    pptr->icmphdr.code > info->icmpv6_code[1]))
			return false;
	}
	return true;
}