static int tcf_ipt_cleanup(struct tc_action *a, int bind) { struct tcf_ipt *ipt = a->priv; return tcf_ipt_release(ipt, bind); }
static int tcf_ipt_init(struct nlattr *nla, struct nlattr *est, struct tc_action *a, int ovr, int bind) { struct nlattr *tb[TCA_IPT_MAX + 1]; struct tcf_ipt *ipt; struct tcf_common *pc; struct xt_entry_target *td, *t; char *tname; int ret = 0, err; u32 hook = 0; u32 index = 0; if (nla == NULL) return -EINVAL; err = nla_parse_nested(tb, TCA_IPT_MAX, nla, ipt_policy); if (err < 0) return err; if (tb[TCA_IPT_HOOK] == NULL) return -EINVAL; if (tb[TCA_IPT_TARG] == NULL) return -EINVAL; td = (struct xt_entry_target *)nla_data(tb[TCA_IPT_TARG]); if (nla_len(tb[TCA_IPT_TARG]) < td->u.target_size) return -EINVAL; if (tb[TCA_IPT_INDEX] != NULL) index = nla_get_u32(tb[TCA_IPT_INDEX]); pc = tcf_hash_check(index, a, bind, &ipt_hash_info); if (!pc) { pc = tcf_hash_create(index, est, a, sizeof(*ipt), bind, &ipt_idx_gen, &ipt_hash_info); if (IS_ERR(pc)) return PTR_ERR(pc); ret = ACT_P_CREATED; } else { if (!ovr) { tcf_ipt_release(to_ipt(pc), bind); return -EEXIST; } } ipt = to_ipt(pc); hook = nla_get_u32(tb[TCA_IPT_HOOK]); err = -ENOMEM; tname = kmalloc(IFNAMSIZ, GFP_KERNEL); if (unlikely(!tname)) goto err1; if (tb[TCA_IPT_TABLE] == NULL || nla_strlcpy(tname, tb[TCA_IPT_TABLE], IFNAMSIZ) >= IFNAMSIZ) strcpy(tname, "mangle"); t = kmemdup(td, td->u.target_size, GFP_KERNEL); if (unlikely(!t)) goto err2; err = ipt_init_target(t, tname, hook); if (err < 0) goto err3; spin_lock_bh(&ipt->tcf_lock); if (ret != ACT_P_CREATED) { ipt_destroy_target(ipt->tcfi_t); kfree(ipt->tcfi_tname); kfree(ipt->tcfi_t); } ipt->tcfi_tname = tname; ipt->tcfi_t = t; ipt->tcfi_hook = hook; spin_unlock_bh(&ipt->tcf_lock); if (ret == ACT_P_CREATED) tcf_hash_insert(pc, &ipt_hash_info); return ret; err3: kfree(t); err2: kfree(tname); err1: if (ret == ACT_P_CREATED) { if (est) gen_kill_estimator(&pc->tcfc_bstats, &pc->tcfc_rate_est); kfree_rcu(pc, tcfc_rcu); } return err; }
static int tcf_ipt_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a, int ovr, int bind) { struct rtattr *tb[TCA_IPT_MAX]; struct tcf_ipt *p; struct ipt_entry_target *td, *t; char *tname; int ret = 0, err; u32 hook = 0; u32 index = 0; if (rta == NULL || rtattr_parse_nested(tb, TCA_IPT_MAX, rta) < 0) return -EINVAL; if (tb[TCA_IPT_HOOK-1] == NULL || RTA_PAYLOAD(tb[TCA_IPT_HOOK-1]) < sizeof(u32)) return -EINVAL; if (tb[TCA_IPT_TARG-1] == NULL || RTA_PAYLOAD(tb[TCA_IPT_TARG-1]) < sizeof(*t)) return -EINVAL; td = (struct ipt_entry_target *)RTA_DATA(tb[TCA_IPT_TARG-1]); if (RTA_PAYLOAD(tb[TCA_IPT_TARG-1]) < td->u.target_size) return -EINVAL; if (tb[TCA_IPT_INDEX-1] != NULL && RTA_PAYLOAD(tb[TCA_IPT_INDEX-1]) >= sizeof(u32)) index = *(u32 *)RTA_DATA(tb[TCA_IPT_INDEX-1]); p = tcf_hash_check(index, a, ovr, bind); if (p == NULL) { p = tcf_hash_create(index, est, a, sizeof(*p), ovr, bind); if (p == NULL) return -ENOMEM; ret = ACT_P_CREATED; } else { if (!ovr) { tcf_ipt_release(p, bind); return -EEXIST; } } hook = *(u32 *)RTA_DATA(tb[TCA_IPT_HOOK-1]); err = -ENOMEM; tname = kmalloc(IFNAMSIZ, GFP_KERNEL); if (tname == NULL) goto err1; if (tb[TCA_IPT_TABLE - 1] == NULL || rtattr_strlcpy(tname, tb[TCA_IPT_TABLE-1], IFNAMSIZ) >= IFNAMSIZ) strcpy(tname, "mangle"); t = kmalloc(td->u.target_size, GFP_KERNEL); if (t == NULL) goto err2; memcpy(t, td, td->u.target_size); if ((err = ipt_init_target(t, tname, hook)) < 0) goto err3; spin_lock_bh(&p->lock); if (ret != ACT_P_CREATED) { ipt_destroy_target(p->t); kfree(p->tname); kfree(p->t); } p->tname = tname; p->t = t; p->hook = hook; spin_unlock_bh(&p->lock); if (ret == ACT_P_CREATED) tcf_hash_insert(p); return ret; err3: kfree(t); err2: kfree(tname); err1: kfree(p); return err; }
static int tcf_ipt_cleanup(struct tc_action *a, int bind) { struct tcf_ipt *p = PRIV(a, ipt); return tcf_ipt_release(p, bind); }
static int tcf_ipt_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a, int ovr, int bind) { struct rtattr *tb[TCA_IPT_MAX]; struct tcf_ipt *ipt; struct tcf_common *pc; struct ipt_entry_target *td, *t; char *tname; int ret = 0, err; u32 hook = 0; u32 index = 0; if (rta == NULL || rtattr_parse_nested(tb, TCA_IPT_MAX, rta) < 0) return -EINVAL; if (tb[TCA_IPT_HOOK-1] == NULL || RTA_PAYLOAD(tb[TCA_IPT_HOOK-1]) < sizeof(u32)) return -EINVAL; if (tb[TCA_IPT_TARG-1] == NULL || RTA_PAYLOAD(tb[TCA_IPT_TARG-1]) < sizeof(*t)) return -EINVAL; td = (struct ipt_entry_target *)RTA_DATA(tb[TCA_IPT_TARG-1]); if (RTA_PAYLOAD(tb[TCA_IPT_TARG-1]) < td->u.target_size) return -EINVAL; if (tb[TCA_IPT_INDEX-1] != NULL && RTA_PAYLOAD(tb[TCA_IPT_INDEX-1]) >= sizeof(u32)) index = *(u32 *)RTA_DATA(tb[TCA_IPT_INDEX-1]); pc = tcf_hash_check(index, a, bind, &ipt_hash_info); if (!pc) { pc = tcf_hash_create(index, est, a, sizeof(*ipt), bind, &ipt_idx_gen, &ipt_hash_info); if (unlikely(!pc)) return -ENOMEM; ret = ACT_P_CREATED; } else { if (!ovr) { tcf_ipt_release(to_ipt(pc), bind); return -EEXIST; } } ipt = to_ipt(pc); hook = *(u32 *)RTA_DATA(tb[TCA_IPT_HOOK-1]); err = -ENOMEM; tname = kmalloc(IFNAMSIZ, GFP_KERNEL); if (unlikely(!tname)) goto err1; if (tb[TCA_IPT_TABLE - 1] == NULL || rtattr_strlcpy(tname, tb[TCA_IPT_TABLE-1], IFNAMSIZ) >= IFNAMSIZ) strcpy(tname, "mangle"); t = kmemdup(td, td->u.target_size, GFP_KERNEL); if (unlikely(!t)) goto err2; if ((err = ipt_init_target(t, tname, hook)) < 0) goto err3; spin_lock_bh(&ipt->tcf_lock); if (ret != ACT_P_CREATED) { ipt_destroy_target(ipt->tcfi_t); kfree(ipt->tcfi_tname); kfree(ipt->tcfi_t); } ipt->tcfi_tname = tname; ipt->tcfi_t = t; ipt->tcfi_hook = hook; spin_unlock_bh(&ipt->tcf_lock); if (ret == ACT_P_CREATED) tcf_hash_insert(pc, &ipt_hash_info); return ret; err3: kfree(t); err2: kfree(tname); err1: kfree(pc); return err; }