Exemplo n.º 1
0
static int ebt_among_check(const char *tablename, unsigned int hookmask,
			   const struct ebt_entry *e, void *data,
			   unsigned int datalen)
{
	const struct ebt_among_info *info = data;
	int expected_length = sizeof(struct ebt_among_info);
	const struct ebt_mac_wormhash *wh_dst, *wh_src;
	int err;

	wh_dst = ebt_among_wh_dst(info);
	wh_src = ebt_among_wh_src(info);
	expected_length += ebt_mac_wormhash_size(wh_dst);
	expected_length += ebt_mac_wormhash_size(wh_src);

	if (datalen != EBT_ALIGN(expected_length)) {
		printk(KERN_WARNING
		       "ebtables: among: wrong size: %d "
		       "against expected %d, rounded to %Zd\n",
		       datalen, expected_length,
		       EBT_ALIGN(expected_length));
		return -EINVAL;
	}
	if (wh_dst && (err = ebt_mac_wormhash_check_integrity(wh_dst))) {
		printk(KERN_WARNING
		       "ebtables: among: dst integrity fail: %x\n", -err);
		return -EINVAL;
	}
	if (wh_src && (err = ebt_mac_wormhash_check_integrity(wh_src))) {
		printk(KERN_WARNING
		       "ebtables: among: src integrity fail: %x\n", -err);
		return -EINVAL;
	}
	return 0;
}
Exemplo n.º 2
0
static int ebt_among_mt_check(const struct xt_mtchk_param *par) {
  const struct ebt_among_info *info = par->matchinfo;
  const struct ebt_entry_match *em =
    container_of(par->matchinfo, const struct ebt_entry_match, data);
  int expected_length = sizeof(struct ebt_among_info);
  const struct ebt_mac_wormhash *wh_dst, *wh_src;
  int err;

  wh_dst = ebt_among_wh_dst(info);
  wh_src = ebt_among_wh_src(info);
  expected_length += ebt_mac_wormhash_size(wh_dst);
  expected_length += ebt_mac_wormhash_size(wh_src);

  if (em->match_size != EBT_ALIGN(expected_length)) {
    pr_info("wrong size: %d against expected %d, rounded to %Zd\n",
            em->match_size, expected_length,
            EBT_ALIGN(expected_length));
    return -EINVAL;
  }
  if (wh_dst && (err = ebt_mac_wormhash_check_integrity(wh_dst))) {
    pr_info("dst integrity fail: %x\n", -err);
    return -EINVAL;
  }
  if (wh_src && (err = ebt_mac_wormhash_check_integrity(wh_src))) {
    pr_info("src integrity fail: %x\n", -err);
    return -EINVAL;
  }
  return 0;
}
Exemplo n.º 3
0
static bool ebt_among_mt_check(const struct xt_mtchk_param *par)
{
	const struct ebt_among_info *info = par->matchinfo;
	const struct ebt_entry_match *em =
		container_of(par->matchinfo, const struct ebt_entry_match, data);
	int expected_length = sizeof(struct ebt_among_info);
	const struct ebt_mac_wormhash *wh_dst, *wh_src;
	int err;

	wh_dst = ebt_among_wh_dst(info);
	wh_src = ebt_among_wh_src(info);
	expected_length += ebt_mac_wormhash_size(wh_dst);
	expected_length += ebt_mac_wormhash_size(wh_src);

	if (em->match_size != EBT_ALIGN(expected_length)) {
		printk(KERN_WARNING
		       "ebtables: among: wrong size: %d "
		       "against expected %d, rounded to %Zd\n",
		       em->match_size, expected_length,
		       EBT_ALIGN(expected_length));
		return false;
	}
	if (wh_dst && (err = ebt_mac_wormhash_check_integrity(wh_dst))) {
		printk(KERN_WARNING
		       "ebtables: among: dst integrity fail: %x\n", -err);
		return false;
	}
	if (wh_src && (err = ebt_mac_wormhash_check_integrity(wh_src))) {
		printk(KERN_WARNING
		       "ebtables: among: src integrity fail: %x\n", -err);
		return false;
	}
	return true;
}
Exemplo n.º 4
0
static int ebt_ip_check(const char *tablename, unsigned int hookmask,
   const struct ebt_entry *e, void *data, unsigned int datalen)
{
	struct ebt_ip_info *info = (struct ebt_ip_info *)data;

	if (datalen != EBT_ALIGN(sizeof(struct ebt_ip_info)))
		return -EINVAL;
	if (e->ethproto != __constant_htons(ETH_P_IP) ||
	   e->invflags & EBT_IPROTO)
		return -EINVAL;
	if (info->bitmask & ~EBT_IP_MASK || info->invflags & ~EBT_IP_MASK)
		return -EINVAL;
	if (info->bitmask & (EBT_IP_DPORT | EBT_IP_SPORT)) {
		if (!info->bitmask & EBT_IPROTO)
			return -EINVAL;
		if (info->protocol != IPPROTO_TCP &&
		    info->protocol != IPPROTO_UDP)
			 return -EINVAL;
	}
	if (info->bitmask & EBT_IP_DPORT && info->dport[0] > info->dport[1])
		return -EINVAL;
	if (info->bitmask & EBT_IP_SPORT && info->sport[0] > info->sport[1])
		return -EINVAL;
	return 0;
}
static int ebt_pkttype_check(const char *tablename, unsigned int hookmask,
   const struct ebt_entry *e, void *data, unsigned int datalen)
{
	struct ebt_pkttype_info *info = (struct ebt_pkttype_info *)data;

	if (datalen != EBT_ALIGN(sizeof(struct ebt_pkttype_info)))
		return -EINVAL;
	if (info->invert != 0 && info->invert != 1)
		return -EINVAL;
	/* Allow any pkt_type value */
	return 0;
}
Exemplo n.º 6
0
static int ebt_target_mark_check(const char *tablename, unsigned int hookmask,
   const struct ebt_entry *e, void *data, unsigned int datalen)
{
	struct ebt_mark_t_info *info = (struct ebt_mark_t_info *)data;

	if (datalen != EBT_ALIGN(sizeof(struct ebt_mark_t_info)))
		return -EINVAL;
	if (BASE_CHAIN && info->target == EBT_RETURN)
		return -EINVAL;
	CLEAR_BASE_CHAIN_BIT;
	if (INVALID_TARGET)
		return -EINVAL;
	return 0;
}
Exemplo n.º 7
0
static int ebt_log_check(const char *tablename, unsigned int hookmask,
   const struct ebt_entry *e, void *data, unsigned int datalen)
{
	struct ebt_log_info *info = (struct ebt_log_info *)data;

	if (datalen != EBT_ALIGN(sizeof(struct ebt_log_info)))
		return -EINVAL;
	if (info->bitmask & ~EBT_LOG_MASK)
		return -EINVAL;
	if (info->loglevel >= 8)
		return -EINVAL;
	info->prefix[EBT_LOG_PREFIX_SIZE - 1] = '\0';
	return 0;
}
Exemplo n.º 8
0
static int ebt_arp_check(const char *tablename, unsigned int hookmask,
   const struct ebt_entry *e, void *data, unsigned int datalen)
{
	const struct ebt_arp_info *info = data;

	if (datalen != EBT_ALIGN(sizeof(struct ebt_arp_info)))
		return -EINVAL;
	if ((e->ethproto != htons(ETH_P_ARP) &&
	   e->ethproto != htons(ETH_P_RARP)) ||
	   e->invflags & EBT_IPROTO)
		return -EINVAL;
	if (info->bitmask & ~EBT_ARP_MASK || info->invflags & ~EBT_ARP_MASK)
		return -EINVAL;
	return 0;
}
Exemplo n.º 9
0
static int ebt_ulog_check(const char *tablename, unsigned int hookmask,
   const struct ebt_entry *e, void *data, unsigned int datalen)
{
	struct ebt_ulog_info *uloginfo = (struct ebt_ulog_info *)data;

	if (datalen != EBT_ALIGN(sizeof(struct ebt_ulog_info)) ||
	    uloginfo->nlgroup > 31)
		return -EINVAL;

	uloginfo->prefix[EBT_ULOG_PREFIX_LEN - 1] = '\0';

	if (uloginfo->qthreshold > EBT_ULOG_MAX_QLEN)
		uloginfo->qthreshold = EBT_ULOG_MAX_QLEN;

	return 0;
}
static int ebt_target_reply_check(const char *tablename, unsigned int hookmask,
   const struct ebt_entry *e, void *data, unsigned int datalen)
{
	const struct ebt_arpreply_info *info = data;

	if (datalen != EBT_ALIGN(sizeof(struct ebt_arpreply_info)))
		return -EINVAL;
	if (BASE_CHAIN && info->target == EBT_RETURN)
		return -EINVAL;
	if (e->ethproto != htons(ETH_P_ARP) ||
	    e->invflags & EBT_IPROTO)
		return -EINVAL;
	CLEAR_BASE_CHAIN_BIT;
	if (strcmp(tablename, "nat") || hookmask & ~(1 << NF_BR_PRE_ROUTING))
		return -EINVAL;
	return 0;
}
Exemplo n.º 11
0
static int ebt_target_redirect_check(const char *tablename, unsigned int hookmask,
                                     const struct ebt_entry *e, void *data, unsigned int datalen)
{
    struct ebt_redirect_info *info = (struct ebt_redirect_info *)data;

    if (datalen != EBT_ALIGN(sizeof(struct ebt_redirect_info)))
        return -EINVAL;
    if (BASE_CHAIN && info->target == EBT_RETURN)
        return -EINVAL;
    CLEAR_BASE_CHAIN_BIT;
    if ( (strcmp(tablename, "nat") || hookmask & ~(1 << NF_BR_PRE_ROUTING)) &&
            (strcmp(tablename, "broute") || hookmask & ~(1 << NF_BR_BROUTING)) )
        return -EINVAL;
    if (INVALID_TARGET)
        return -EINVAL;
    return 0;
}
Exemplo n.º 12
0
static int ebt_stp_check(const char *tablename, unsigned int hookmask,
   const struct ebt_entry *e, void *data, unsigned int datalen)
{
	struct ebt_stp_info *info = (struct ebt_stp_info *)data;
	int len = EBT_ALIGN(sizeof(struct ebt_stp_info));
	uint8_t bridge_ula[6] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
	uint8_t msk[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };

	if (info->bitmask & ~EBT_STP_MASK || info->invflags & ~EBT_STP_MASK ||
	    !(info->bitmask & EBT_STP_MASK))
		return -EINVAL;
	if (datalen != len)
		return -EINVAL;
	/* Make sure the match only receives stp frames */
	if (compare_ether_addr(e->destmac, bridge_ula) ||
	    compare_ether_addr(e->destmsk, msk) || !(e->bitmask & EBT_DESTMAC))
		return -EINVAL;

	return 0;
}
Exemplo n.º 13
0
static int ebt_limit_check(const char *tablename, unsigned int hookmask,
   const struct ebt_entry *e, void *data, unsigned int datalen)
{
	struct ebt_limit_info *info = data;

	if (datalen != EBT_ALIGN(sizeof(struct ebt_limit_info)))
		return -EINVAL;

	/* Check for overflow. */
	if (info->burst == 0 ||
	    user2credits(info->avg * info->burst) < user2credits(info->avg)) {
		printk("Overflow in ebt_limit, try lower: %u/%u\n",
			info->avg, info->burst);
		return -EINVAL;
	}

	/* User avg in seconds * EBT_LIMIT_SCALE: convert to jiffies * 128. */
	info->prev = jiffies;
	info->credit = user2credits(info->avg * info->burst);
	info->credit_cap = user2credits(info->avg * info->burst);
	info->cost = user2credits(info->avg);
	return 0;
}
Exemplo n.º 14
0
static int ebt_target_snat_check(const char *tablename, unsigned int hookmask,
   const struct ebt_entry *e, void *data, unsigned int datalen)
{
    const struct ebt_nat_info *info = data;
    int tmp;

    if (datalen != EBT_ALIGN(sizeof(struct ebt_nat_info)))
        return -EINVAL;
    tmp = info->target | ~EBT_VERDICT_BITS;
    if (BASE_CHAIN && tmp == EBT_RETURN)
        return -EINVAL;
    CLEAR_BASE_CHAIN_BIT;
    if (strcmp(tablename, "nat"))
        return -EINVAL;
    if (hookmask & ~(1 << NF_BR_POST_ROUTING))
        return -EINVAL;

    if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0)
        return -EINVAL;
    tmp = info->target | EBT_VERDICT_BITS;
    if ((tmp & ~NAT_ARP_BIT) != ~NAT_ARP_BIT)
        return -EINVAL;
    return 0;
}
Exemplo n.º 15
0
static int
ebt_target_vlan_check(const char *tablename,
	       unsigned int hooknr,
	       const struct ebt_entry *e, void *data, unsigned int datalen)
{
	struct ebt_vlan_t_info *info = (struct ebt_vlan_t_info *) data;

	/* Parameters buffer overflow check */
	if (datalen != EBT_ALIGN(sizeof(struct ebt_vlan_t_info))) {
		DEBUG_MSG
		    ("passed size %d is not eq to ebt_vlan_info (%Zd)\n",
		     datalen, sizeof(struct ebt_vlan_t_info));
		return -EINVAL;
	}

	/* Is it 802.1Q frame checked? */
	if (e->ethproto != __constant_htons(ETH_P_8021Q)) {
		DEBUG_MSG
		    ("passed entry proto %2.4X is not 802.1Q (8100)\n",
		     (unsigned short) ntohs(e->ethproto));
		return -EINVAL;
	}

	/* Check for bitmask range
	 * True if even one bit is out of mask */
	if (info->bitmask & ~EBT_VLAN_TARGET_MASK) {
		DEBUG_MSG("bitmask %2X is out of mask (%2X)\n",
			  info->bitmask, EBT_VLAN_TARGET_MASK);
		return -EINVAL;
	}


	/* Reserved VLAN ID (VID) values
	 * -----------------------------
	 * 0 - The null VLAN ID. 
	 * 1 - The default Port VID (PVID)
	 * 0x0FFF - Reserved for implementation use. 
	 * if_vlan.h: VLAN_GROUP_ARRAY_LEN 4096. */
	if (GET_BITMASK(EBT_VLAN_TARGET_ID)) {
		if (!!info->id) { /* if id!=0 => check vid range */
			if (info->id > VLAN_GROUP_ARRAY_LEN) {
				DEBUG_MSG
				    ("id %d is out of range (1-4094)\n",
				     info->id);
				return -EINVAL;
			}


	#if 0
			/* Note: This is valid VLAN-tagged frame point.
			 * Any value of user_priority are acceptable, 
			 * but should be ignored according to 802.1Q Std.
			 * So we just drop the prio flag. */
			info->bitmask &= ~EBT_VLAN_TARGET_PRIO;
	#endif
		}
	#if 0 /*w00135358 -- VLAN ID == 0 is OK for VLAN ID Remark -- 20080928 */	
		else
		{
			return -EINVAL;
		}
	#endif	
	}

	if (GET_BITMASK(EBT_VLAN_TARGET_PRIO)) {
		if ((unsigned char) info->prio > 7) {
			DEBUG_MSG("prio %d is out of range (0-7)\n",
			     info->prio);
			return -EINVAL;
		}
	}

	return 0;
}
Exemplo n.º 16
0
static int parse(int c, char **argv, int argc,
		 const struct ebt_u_entry *entry, unsigned int *flags,
		 struct ebt_entry_match **match)
{
	struct ebt_among_info *info =
	    (struct ebt_among_info *) (*match)->data;
	struct ebt_mac_wormhash *wh;
	struct ebt_entry_match *h;
	int new_size;
	long flen;
	int fd;

	switch (c) {
	case AMONG_DST_F:
	case AMONG_SRC_F:
	case AMONG_DST:
	case AMONG_SRC:
		if (c == AMONG_DST || c == AMONG_DST_F) {
			ebt_check_option2(flags, OPT_DST);
		} else {
			ebt_check_option2(flags, OPT_SRC);
		}
		if (ebt_check_inverse2(optarg)) {
			if (c == AMONG_DST || c == AMONG_DST_F)
				info->bitmask |= EBT_AMONG_DST_NEG;
			else
				info->bitmask |= EBT_AMONG_SRC_NEG;
		}
		if (c == AMONG_DST_F || c == AMONG_SRC_F) {
			struct stat stats;

			if ((fd = open(optarg, O_RDONLY)) == -1)
				ebt_print_error("Couldn't open file '%s'", optarg);
			fstat(fd, &stats);
			flen = stats.st_size;
			/* use mmap because the file will probably be big */
			optarg = mmap(0, flen, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
			if (optarg == MAP_FAILED)
				ebt_print_error("Couldn't map file to memory");
			if (optarg[flen-1] != '\n')
				ebt_print_error("File should end with a newline");
			if (strchr(optarg, '\n') != optarg+flen-1)
				ebt_print_error("File should only contain one line");
			optarg[flen-1] = '\0';
			if (ebt_errormsg[0] != '\0') {
				munmap(argv, flen);
				close(fd);
				exit(-1);
			}
		}
		wh = create_wormhash(optarg);
		if (ebt_errormsg[0] != '\0')
			break;

		new_size = old_size+ebt_mac_wormhash_size(wh);
		h = malloc(sizeof(struct ebt_entry_match)+EBT_ALIGN(new_size));
		if (!h)
			ebt_print_memory();
		memcpy(h, *match, old_size+sizeof(struct ebt_entry_match));
		memcpy((char *)h+old_size+sizeof(struct ebt_entry_match), wh,
		       ebt_mac_wormhash_size(wh));
		h->match_size = EBT_ALIGN(new_size);
		info = (struct ebt_among_info *) h->data;
		if (c == AMONG_DST) {
			info->wh_dst_ofs = old_size;
		} else {
			info->wh_src_ofs = old_size;
		}
		old_size = new_size;
		free(*match);
		*match = h;
		free(wh);
		if (c == AMONG_DST_F || c == AMONG_SRC_F) {
			munmap(argv, flen);
			close(fd);
		}
		break;
	default:
		return 0;
	}
	return 1;
}