Input:
static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
			     struct netlink_ext_ack *extack)
{
	struct net *net = sock_net(in_skb->sk);
	struct rtmsg *rtm;
	struct nlattr *tb[RTA_MAX+1];
	struct fib_result res = {};
	struct rtable *rt = NULL;
	struct flowi4 fl4;
	__be32 dst = 0;
	__be32 src = 0;
	u32 iif;
	int err;
	int mark;
	struct sk_buff *skb;
	u32 table_id = RT_TABLE_MAIN;
	kuid_t uid;

	err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv4_policy,
			  extack);
	if (err < 0)
		goto errout;

	rtm = nlmsg_data(nlh);

	skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
	if (!skb) {
		err = -ENOBUFS;
		goto errout;
	}

	/* Reserve room for dummy headers, this skb can pass
	   through good chunk of routing engine.
	 */
	skb_reset_mac_header(skb);
	skb_reset_network_header(skb);

	src = tb[RTA_SRC] ? nla_get_in_addr(tb[RTA_SRC]) : 0;
	dst = tb[RTA_DST] ? nla_get_in_addr(tb[RTA_DST]) : 0;
	iif = tb[RTA_IIF] ? nla_get_u32(tb[RTA_IIF]) : 0;
	mark = tb[RTA_MARK] ? nla_get_u32(tb[RTA_MARK]) : 0;
	if (tb[RTA_UID])
		uid = make_kuid(current_user_ns(), nla_get_u32(tb[RTA_UID]));
	else
		uid = (iif ? INVALID_UID : current_uid());

	/* Bugfix: need to give ip_route_input enough of an IP header to
	 * not gag.
	 */
	ip_hdr(skb)->protocol = IPPROTO_UDP;
	ip_hdr(skb)->saddr = src;
	ip_hdr(skb)->daddr = dst;

	skb_reserve(skb, MAX_HEADER + sizeof(struct iphdr));

	memset(&fl4, 0, sizeof(fl4));
	fl4.daddr = dst;
	fl4.saddr = src;
	fl4.flowi4_tos = rtm->rtm_tos;
	fl4.flowi4_oif = tb[RTA_OIF] ? nla_get_u32(tb[RTA_OIF]) : 0;
	fl4.flowi4_mark = mark;
	fl4.flowi4_uid = uid;

	rcu_read_lock();

	if (iif) {
		struct net_device *dev;

		dev = dev_get_by_index_rcu(net, iif);
		if (!dev) {
			err = -ENODEV;
			goto errout_free;
		}

		skb->protocol	= htons(ETH_P_IP);
		skb->dev	= dev;
		skb->mark	= mark;
		err = ip_route_input_rcu(skb, dst, src, rtm->rtm_tos,
					 dev, &res);

		rt = skb_rtable(skb);
		if (err == 0 && rt->dst.error)
			err = -rt->dst.error;
	} else {
		rt = ip_route_output_key_hash_rcu(net, &fl4, &res, skb);
		err = 0;
		if (IS_ERR(rt))
			err = PTR_ERR(rt);
		else
			skb_dst_set(skb, &rt->dst);
	}

	if (err)
		goto errout_free;

	if (rtm->rtm_flags & RTM_F_NOTIFY)
		rt->rt_flags |= RTCF_NOTIFY;

	if (rtm->rtm_flags & RTM_F_LOOKUP_TABLE)
		table_id = rt->rt_table_id;

	if (rtm->rtm_flags & RTM_F_FIB_MATCH)
		err = fib_dump_info(skb, NETLINK_CB(in_skb).portid,
				    nlh->nlmsg_seq, RTM_NEWROUTE, table_id,
				    rt->rt_type, res.prefix, res.prefixlen,
				    fl4.flowi4_tos, res.fi, 0);
	else
		err = rt_fill_info(net, dst, src, table_id, &fl4, skb,
				   NETLINK_CB(in_skb).portid, nlh->nlmsg_seq);
	if (err < 0)
		goto errout_free;

	rcu_read_unlock();

	err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).portid);
errout:
	return err;

errout_free:
	rcu_read_unlock();
	kfree_skb(skb);
	goto errout;
}

static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
			     struct netlink_ext_ack *extack)
{
	struct net *net = sock_net(in_skb->sk);
	struct rtmsg *rtm;
	struct nlattr *tb[RTA_MAX+1];
	struct fib_result res = {};
	struct rtable *rt = NULL;
	struct flowi4 fl4;
	__be32 dst = 0;
	__be32 src = 0;
	u32 iif;
	int err;
	int mark;
	struct sk_buff *skb;
	u32 table_id = RT_TABLE_MAIN;
	kuid_t uid;

	err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv4_policy,
			  extack);
	if (err < 0)
		goto errout;

	rtm = nlmsg_data(nlh);

	skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
	if (!skb) {
		err = -ENOBUFS;
		goto errout;
	}

	/* Reserve room for dummy headers, this skb can pass
	   through good chunk of routing engine.
	 */
	skb_reset_mac_header(skb);
	skb_reset_network_header(skb);

	src = tb[RTA_SRC] ? nla_get_in_addr(tb[RTA_SRC]) : 0;
	dst = tb[RTA_DST] ? nla_get_in_addr(tb[RTA_DST]) : 0;
	iif = tb[RTA_IIF] ? nla_get_u32(tb[RTA_IIF]) : 0;
	mark = tb[RTA_MARK] ? nla_get_u32(tb[RTA_MARK]) : 0;
	if (tb[RTA_UID])
		uid = make_kuid(current_user_ns(), nla_get_u32(tb[RTA_UID]));
	else
		uid = (iif ? INVALID_UID : current_uid());

	/* Bugfix: need to give ip_route_input enough of an IP header to
	 * not gag.
	 */
	ip_hdr(skb)->protocol = IPPROTO_UDP;
	ip_hdr(skb)->saddr = src;
	ip_hdr(skb)->daddr = dst;

	skb_reserve(skb, MAX_HEADER + sizeof(struct iphdr));

	memset(&fl4, 0, sizeof(fl4));
	fl4.daddr = dst;
	fl4.saddr = src;
	fl4.flowi4_tos = rtm->rtm_tos;
	fl4.flowi4_oif = tb[RTA_OIF] ? nla_get_u32(tb[RTA_OIF]) : 0;
	fl4.flowi4_mark = mark;
	fl4.flowi4_uid = uid;

	rcu_read_lock();

	if (iif) {
		struct net_device *dev;

		dev = dev_get_by_index_rcu(net, iif);
		if (!dev) {
			err = -ENODEV;
			goto errout_free;
		}

		skb->protocol	= htons(ETH_P_IP);
		skb->dev	= dev;
		skb->mark	= mark;
		err = ip_route_input_rcu(skb, dst, src, rtm->rtm_tos,
					 dev, &res);

		rt = skb_rtable(skb);
		if (err == 0 && rt->dst.error)
			err = -rt->dst.error;
	} else {
		rt = ip_route_output_key_hash_rcu(net, &fl4, &res, skb);
		err = 0;
		if (IS_ERR(rt))
			err = PTR_ERR(rt);
		else
			skb_dst_set(skb, &rt->dst);
	}

	if (err)
		goto errout_free;

	if (rtm->rtm_flags & RTM_F_NOTIFY)
		rt->rt_flags |= RTCF_NOTIFY;

	if (rtm->rtm_flags & RTM_F_LOOKUP_TABLE)
		table_id = rt->rt_table_id;

	if (rtm->rtm_flags & RTM_F_FIB_MATCH) {
		if (!res.fi) {
			err = fib_props[res.type].error;
			if (!err)
				err = -EHOSTUNREACH;
			goto errout_free;
		}
		err = fib_dump_info(skb, NETLINK_CB(in_skb).portid,
				    nlh->nlmsg_seq, RTM_NEWROUTE, table_id,
				    rt->rt_type, res.prefix, res.prefixlen,
				    fl4.flowi4_tos, res.fi, 0);
	} else {
		err = rt_fill_info(net, dst, src, table_id, &fl4, skb,
				   NETLINK_CB(in_skb).portid, nlh->nlmsg_seq);
	}
	if (err < 0)
		goto errout_free;

	rcu_read_unlock();

	err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).portid);
errout:
	return err;

errout_free:
	rcu_read_unlock();
	kfree_skb(skb);
	goto errout;
}


Input:
validate_as_request(kdc_realm_t *kdc_active_realm,
                    register krb5_kdc_req *request, krb5_db_entry client,
                    krb5_db_entry server, krb5_timestamp kdc_time,
                    const char **status, krb5_pa_data ***e_data)
{
    int errcode;
    krb5_error_code ret;

    /*
     * If an option is set that is only allowed in TGS requests, complain.
     */
    if (request->kdc_options & AS_INVALID_OPTIONS) {
        *status = "INVALID AS OPTIONS";
        return KDC_ERR_BADOPTION;
    }

    /* The client must not be expired */
    if (client.expiration && client.expiration < kdc_time) {
        *status = "CLIENT EXPIRED";
        if (vague_errors)
            return(KRB_ERR_GENERIC);
        else
            return(KDC_ERR_NAME_EXP);
    }

    /* The client's password must not be expired, unless the server is
       a KRB5_KDC_PWCHANGE_SERVICE. */
    if (client.pw_expiration && client.pw_expiration < kdc_time &&
        !isflagset(server.attributes, KRB5_KDB_PWCHANGE_SERVICE)) {
        *status = "CLIENT KEY EXPIRED";
        if (vague_errors)
            return(KRB_ERR_GENERIC);
        else
            return(KDC_ERR_KEY_EXP);
    }

    /* The server must not be expired */
    if (server.expiration && server.expiration < kdc_time) {
        *status = "SERVICE EXPIRED";
        return(KDC_ERR_SERVICE_EXP);
    }

    /*
     * If the client requires password changing, then only allow the
     * pwchange service.
     */
    if (isflagset(client.attributes, KRB5_KDB_REQUIRES_PWCHANGE) &&
        !isflagset(server.attributes, KRB5_KDB_PWCHANGE_SERVICE)) {
        *status = "REQUIRED PWCHANGE";
        return(KDC_ERR_KEY_EXP);
    }

    /* Client and server must allow postdating tickets */
    if ((isflagset(request->kdc_options, KDC_OPT_ALLOW_POSTDATE) ||
         isflagset(request->kdc_options, KDC_OPT_POSTDATED)) &&
        (isflagset(client.attributes, KRB5_KDB_DISALLOW_POSTDATED) ||
         isflagset(server.attributes, KRB5_KDB_DISALLOW_POSTDATED))) {
        *status = "POSTDATE NOT ALLOWED";
        return(KDC_ERR_CANNOT_POSTDATE);
    }

    /*
     * A Windows KDC will return KDC_ERR_PREAUTH_REQUIRED instead of
     * KDC_ERR_POLICY in the following case:
     *
     *   - KDC_OPT_FORWARDABLE is set in KDCOptions but local
     *     policy has KRB5_KDB_DISALLOW_FORWARDABLE set for the
     *     client, and;
     *   - KRB5_KDB_REQUIRES_PRE_AUTH is set for the client but
     *     preauthentication data is absent in the request.
     *
     * Hence, this check most be done after the check for preauth
     * data, and is now performed by validate_forwardable() (the
     * contents of which were previously below).
     */

    /* Client and server must allow proxiable tickets */
    if (isflagset(request->kdc_options, KDC_OPT_PROXIABLE) &&
        (isflagset(client.attributes, KRB5_KDB_DISALLOW_PROXIABLE) ||
         isflagset(server.attributes, KRB5_KDB_DISALLOW_PROXIABLE))) {
        *status = "PROXIABLE NOT ALLOWED";
        return(KDC_ERR_POLICY);
    }

    /* Check to see if client is locked out */
    if (isflagset(client.attributes, KRB5_KDB_DISALLOW_ALL_TIX)) {
        *status = "CLIENT LOCKED OUT";
        return(KDC_ERR_CLIENT_REVOKED);
    }

    /* Check to see if server is locked out */
    if (isflagset(server.attributes, KRB5_KDB_DISALLOW_ALL_TIX)) {
        *status = "SERVICE LOCKED OUT";
        return(KDC_ERR_S_PRINCIPAL_UNKNOWN);
    }

    /* Check to see if server is allowed to be a service */
    if (isflagset(server.attributes, KRB5_KDB_DISALLOW_SVR)) {
        *status = "SERVICE NOT ALLOWED";
        return(KDC_ERR_MUST_USE_USER2USER);
    }

    if (check_anon(kdc_active_realm, request->client, request->server) != 0) {
        *status = "ANONYMOUS NOT ALLOWED";
        return(KDC_ERR_POLICY);
    }

    /* Perform KDB module policy checks. */
    ret = krb5_db_check_policy_as(kdc_context, request, &client, &server,
                                  kdc_time, status, e_data);
    if (ret && ret != KRB5_PLUGIN_OP_NOTSUPP)
        return errcode_to_protocol(ret);

    /* Check against local policy. */
    errcode = against_local_policy_as(request, client, server,
                                      kdc_time, status, e_data);
    if (errcode)
        return errcode;

    return 0;
}

validate_as_request(kdc_realm_t *kdc_active_realm,
                    register krb5_kdc_req *request, krb5_db_entry client,
                    krb5_db_entry server, krb5_timestamp kdc_time,
                    const char **status, krb5_pa_data ***e_data)
{
    int errcode;
    krb5_error_code ret;

    /*
     * If an option is set that is only allowed in TGS requests, complain.
     */
    if (request->kdc_options & AS_INVALID_OPTIONS) {
        *status = "INVALID AS OPTIONS";
        return KDC_ERR_BADOPTION;
    }

    /* The client must not be expired */
    if (client.expiration && client.expiration < kdc_time) {
        *status = "CLIENT EXPIRED";
        if (vague_errors)
            return(KRB_ERR_GENERIC);
        else
            return(KDC_ERR_NAME_EXP);
    }

    /* The client's password must not be expired, unless the server is
       a KRB5_KDC_PWCHANGE_SERVICE. */
    if (client.pw_expiration && client.pw_expiration < kdc_time &&
        !isflagset(server.attributes, KRB5_KDB_PWCHANGE_SERVICE)) {
        *status = "CLIENT KEY EXPIRED";
        if (vague_errors)
            return(KRB_ERR_GENERIC);
        else
            return(KDC_ERR_KEY_EXP);
    }

    /* The server must not be expired */
    if (server.expiration && server.expiration < kdc_time) {
        *status = "SERVICE EXPIRED";
        return(KDC_ERR_SERVICE_EXP);
    }

    /*
     * If the client requires password changing, then only allow the
     * pwchange service.
     */
    if (isflagset(client.attributes, KRB5_KDB_REQUIRES_PWCHANGE) &&
        !isflagset(server.attributes, KRB5_KDB_PWCHANGE_SERVICE)) {
        *status = "REQUIRED PWCHANGE";
        return(KDC_ERR_KEY_EXP);
    }

    /* Client and server must allow postdating tickets */
    if ((isflagset(request->kdc_options, KDC_OPT_ALLOW_POSTDATE) ||
         isflagset(request->kdc_options, KDC_OPT_POSTDATED)) &&
        (isflagset(client.attributes, KRB5_KDB_DISALLOW_POSTDATED) ||
         isflagset(server.attributes, KRB5_KDB_DISALLOW_POSTDATED))) {
        *status = "POSTDATE NOT ALLOWED";
        return(KDC_ERR_CANNOT_POSTDATE);
    }

    /*
     * A Windows KDC will return KDC_ERR_PREAUTH_REQUIRED instead of
     * KDC_ERR_POLICY in the following case:
     *
     *   - KDC_OPT_FORWARDABLE is set in KDCOptions but local
     *     policy has KRB5_KDB_DISALLOW_FORWARDABLE set for the
     *     client, and;
     *   - KRB5_KDB_REQUIRES_PRE_AUTH is set for the client but
     *     preauthentication data is absent in the request.
     *
     * Hence, this check most be done after the check for preauth
     * data, and is now performed by validate_forwardable() (the
     * contents of which were previously below).
     */

    /* Client and server must allow proxiable tickets */
    if (isflagset(request->kdc_options, KDC_OPT_PROXIABLE) &&
        (isflagset(client.attributes, KRB5_KDB_DISALLOW_PROXIABLE) ||
         isflagset(server.attributes, KRB5_KDB_DISALLOW_PROXIABLE))) {
        *status = "PROXIABLE NOT ALLOWED";
        return(KDC_ERR_POLICY);
    }

    /* Check to see if client is locked out */
    if (isflagset(client.attributes, KRB5_KDB_DISALLOW_ALL_TIX)) {
        *status = "CLIENT LOCKED OUT";
        return(KDC_ERR_CLIENT_REVOKED);
    }

    /* Check to see if server is locked out */
    if (isflagset(server.attributes, KRB5_KDB_DISALLOW_ALL_TIX)) {
        *status = "SERVICE LOCKED OUT";
        return(KDC_ERR_S_PRINCIPAL_UNKNOWN);
    }

    /* Check to see if server is allowed to be a service */
    if (isflagset(server.attributes, KRB5_KDB_DISALLOW_SVR)) {
        *status = "SERVICE NOT ALLOWED";
        return(KDC_ERR_MUST_USE_USER2USER);
    }

    if (check_anon(kdc_active_realm, client.princ, request->server) != 0) {
        *status = "ANONYMOUS NOT ALLOWED";
        return(KDC_ERR_POLICY);
    }

    /* Perform KDB module policy checks. */
    ret = krb5_db_check_policy_as(kdc_context, request, &client, &server,
                                  kdc_time, status, e_data);
    if (ret && ret != KRB5_PLUGIN_OP_NOTSUPP)
        return errcode_to_protocol(ret);

    /* Check against local policy. */
    errcode = against_local_policy_as(request, client, server,
                                      kdc_time, status, e_data);
    if (errcode)
        return errcode;

    return 0;
}


Input:
int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
{
	int r;
	/* Assume we're using HV mode when the HV module is loaded */
	int hv_enabled = kvmppc_hv_ops ? 1 : 0;

	if (kvm) {
		/*
		 * Hooray - we know which VM type we're running on. Depend on
		 * that rather than the guess above.
		 */
		hv_enabled = is_kvmppc_hv_enabled(kvm);
	}

	switch (ext) {
#ifdef CONFIG_BOOKE
	case KVM_CAP_PPC_BOOKE_SREGS:
	case KVM_CAP_PPC_BOOKE_WATCHDOG:
	case KVM_CAP_PPC_EPR:
#else
	case KVM_CAP_PPC_SEGSTATE:
	case KVM_CAP_PPC_HIOR:
	case KVM_CAP_PPC_PAPR:
#endif
	case KVM_CAP_PPC_UNSET_IRQ:
	case KVM_CAP_PPC_IRQ_LEVEL:
	case KVM_CAP_ENABLE_CAP:
	case KVM_CAP_ENABLE_CAP_VM:
	case KVM_CAP_ONE_REG:
	case KVM_CAP_IOEVENTFD:
	case KVM_CAP_DEVICE_CTRL:
	case KVM_CAP_IMMEDIATE_EXIT:
		r = 1;
		break;
	case KVM_CAP_PPC_PAIRED_SINGLES:
	case KVM_CAP_PPC_OSI:
	case KVM_CAP_PPC_GET_PVINFO:
#if defined(CONFIG_KVM_E500V2) || defined(CONFIG_KVM_E500MC)
	case KVM_CAP_SW_TLB:
#endif
		/* We support this only for PR */
		r = !hv_enabled;
		break;
#ifdef CONFIG_KVM_MPIC
	case KVM_CAP_IRQ_MPIC:
		r = 1;
		break;
#endif

#ifdef CONFIG_PPC_BOOK3S_64
	case KVM_CAP_SPAPR_TCE:
	case KVM_CAP_SPAPR_TCE_64:
		/* fallthrough */
	case KVM_CAP_SPAPR_TCE_VFIO:
	case KVM_CAP_PPC_RTAS:
	case KVM_CAP_PPC_FIXUP_HCALL:
	case KVM_CAP_PPC_ENABLE_HCALL:
#ifdef CONFIG_KVM_XICS
	case KVM_CAP_IRQ_XICS:
#endif
		r = 1;
		break;

	case KVM_CAP_PPC_ALLOC_HTAB:
		r = hv_enabled;
		break;
#endif /* CONFIG_PPC_BOOK3S_64 */
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
	case KVM_CAP_PPC_SMT:
		r = 0;
		if (kvm) {
			if (kvm->arch.emul_smt_mode > 1)
				r = kvm->arch.emul_smt_mode;
			else
				r = kvm->arch.smt_mode;
		} else if (hv_enabled) {
			if (cpu_has_feature(CPU_FTR_ARCH_300))
				r = 1;
			else
				r = threads_per_subcore;
		}
		break;
	case KVM_CAP_PPC_SMT_POSSIBLE:
		r = 1;
		if (hv_enabled) {
			if (!cpu_has_feature(CPU_FTR_ARCH_300))
				r = ((threads_per_subcore << 1) - 1);
			else
				/* P9 can emulate dbells, so allow any mode */
				r = 8 | 4 | 2 | 1;
		}
		break;
	case KVM_CAP_PPC_RMA:
		r = 0;
		break;
	case KVM_CAP_PPC_HWRNG:
		r = kvmppc_hwrng_present();
		break;
	case KVM_CAP_PPC_MMU_RADIX:
		r = !!(hv_enabled && radix_enabled());
		break;
	case KVM_CAP_PPC_MMU_HASH_V3:
		r = !!(hv_enabled && !radix_enabled() &&
		       cpu_has_feature(CPU_FTR_ARCH_300));
		break;
#endif
	case KVM_CAP_SYNC_MMU:
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
		r = hv_enabled;
#elif defined(KVM_ARCH_WANT_MMU_NOTIFIER)
		r = 1;
#else
		r = 0;
#endif
		break;
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
	case KVM_CAP_PPC_HTAB_FD:
		r = hv_enabled;
		break;
#endif
	case KVM_CAP_NR_VCPUS:
		/*
		 * Recommending a number of CPUs is somewhat arbitrary; we
		 * return the number of present CPUs for -HV (since a host
		 * will have secondary threads "offline"), and for other KVM
		 * implementations just count online CPUs.
		 */
		if (hv_enabled)
			r = num_present_cpus();
		else
			r = num_online_cpus();
		break;
	case KVM_CAP_NR_MEMSLOTS:
		r = KVM_USER_MEM_SLOTS;
		break;
	case KVM_CAP_MAX_VCPUS:
		r = KVM_MAX_VCPUS;
		break;
#ifdef CONFIG_PPC_BOOK3S_64
	case KVM_CAP_PPC_GET_SMMU_INFO:
		r = 1;
		break;
	case KVM_CAP_SPAPR_MULTITCE:
		r = 1;
		break;
	case KVM_CAP_SPAPR_RESIZE_HPT:
		/* Disable this on POWER9 until code handles new HPTE format */
		r = !!hv_enabled && !cpu_has_feature(CPU_FTR_ARCH_300);
		break;
#endif
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
	case KVM_CAP_PPC_FWNMI:
		r = hv_enabled;
		break;
#endif
	case KVM_CAP_PPC_HTM:
		r = cpu_has_feature(CPU_FTR_TM_COMP) &&
		    is_kvmppc_hv_enabled(kvm);
		break;
	default:
		r = 0;
		break;
	}
	return r;

}

int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
{
	int r;
	/* Assume we're using HV mode when the HV module is loaded */
	int hv_enabled = kvmppc_hv_ops ? 1 : 0;

	if (kvm) {
		/*
		 * Hooray - we know which VM type we're running on. Depend on
		 * that rather than the guess above.
		 */
		hv_enabled = is_kvmppc_hv_enabled(kvm);
	}

	switch (ext) {
#ifdef CONFIG_BOOKE
	case KVM_CAP_PPC_BOOKE_SREGS:
	case KVM_CAP_PPC_BOOKE_WATCHDOG:
	case KVM_CAP_PPC_EPR:
#else
	case KVM_CAP_PPC_SEGSTATE:
	case KVM_CAP_PPC_HIOR:
	case KVM_CAP_PPC_PAPR:
#endif
	case KVM_CAP_PPC_UNSET_IRQ:
	case KVM_CAP_PPC_IRQ_LEVEL:
	case KVM_CAP_ENABLE_CAP:
	case KVM_CAP_ENABLE_CAP_VM:
	case KVM_CAP_ONE_REG:
	case KVM_CAP_IOEVENTFD:
	case KVM_CAP_DEVICE_CTRL:
	case KVM_CAP_IMMEDIATE_EXIT:
		r = 1;
		break;
	case KVM_CAP_PPC_PAIRED_SINGLES:
	case KVM_CAP_PPC_OSI:
	case KVM_CAP_PPC_GET_PVINFO:
#if defined(CONFIG_KVM_E500V2) || defined(CONFIG_KVM_E500MC)
	case KVM_CAP_SW_TLB:
#endif
		/* We support this only for PR */
		r = !hv_enabled;
		break;
#ifdef CONFIG_KVM_MPIC
	case KVM_CAP_IRQ_MPIC:
		r = 1;
		break;
#endif

#ifdef CONFIG_PPC_BOOK3S_64
	case KVM_CAP_SPAPR_TCE:
	case KVM_CAP_SPAPR_TCE_64:
		/* fallthrough */
	case KVM_CAP_SPAPR_TCE_VFIO:
	case KVM_CAP_PPC_RTAS:
	case KVM_CAP_PPC_FIXUP_HCALL:
	case KVM_CAP_PPC_ENABLE_HCALL:
#ifdef CONFIG_KVM_XICS
	case KVM_CAP_IRQ_XICS:
#endif
		r = 1;
		break;

	case KVM_CAP_PPC_ALLOC_HTAB:
		r = hv_enabled;
		break;
#endif /* CONFIG_PPC_BOOK3S_64 */
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
	case KVM_CAP_PPC_SMT:
		r = 0;
		if (kvm) {
			if (kvm->arch.emul_smt_mode > 1)
				r = kvm->arch.emul_smt_mode;
			else
				r = kvm->arch.smt_mode;
		} else if (hv_enabled) {
			if (cpu_has_feature(CPU_FTR_ARCH_300))
				r = 1;
			else
				r = threads_per_subcore;
		}
		break;
	case KVM_CAP_PPC_SMT_POSSIBLE:
		r = 1;
		if (hv_enabled) {
			if (!cpu_has_feature(CPU_FTR_ARCH_300))
				r = ((threads_per_subcore << 1) - 1);
			else
				/* P9 can emulate dbells, so allow any mode */
				r = 8 | 4 | 2 | 1;
		}
		break;
	case KVM_CAP_PPC_RMA:
		r = 0;
		break;
	case KVM_CAP_PPC_HWRNG:
		r = kvmppc_hwrng_present();
		break;
	case KVM_CAP_PPC_MMU_RADIX:
		r = !!(hv_enabled && radix_enabled());
		break;
	case KVM_CAP_PPC_MMU_HASH_V3:
		r = !!(hv_enabled && !radix_enabled() &&
		       cpu_has_feature(CPU_FTR_ARCH_300));
		break;
#endif
	case KVM_CAP_SYNC_MMU:
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
		r = hv_enabled;
#elif defined(KVM_ARCH_WANT_MMU_NOTIFIER)
		r = 1;
#else
		r = 0;
#endif
		break;
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
	case KVM_CAP_PPC_HTAB_FD:
		r = hv_enabled;
		break;
#endif
	case KVM_CAP_NR_VCPUS:
		/*
		 * Recommending a number of CPUs is somewhat arbitrary; we
		 * return the number of present CPUs for -HV (since a host
		 * will have secondary threads "offline"), and for other KVM
		 * implementations just count online CPUs.
		 */
		if (hv_enabled)
			r = num_present_cpus();
		else
			r = num_online_cpus();
		break;
	case KVM_CAP_NR_MEMSLOTS:
		r = KVM_USER_MEM_SLOTS;
		break;
	case KVM_CAP_MAX_VCPUS:
		r = KVM_MAX_VCPUS;
		break;
#ifdef CONFIG_PPC_BOOK3S_64
	case KVM_CAP_PPC_GET_SMMU_INFO:
		r = 1;
		break;
	case KVM_CAP_SPAPR_MULTITCE:
		r = 1;
		break;
	case KVM_CAP_SPAPR_RESIZE_HPT:
		/* Disable this on POWER9 until code handles new HPTE format */
		r = !!hv_enabled && !cpu_has_feature(CPU_FTR_ARCH_300);
		break;
#endif
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
	case KVM_CAP_PPC_FWNMI:
		r = hv_enabled;
		break;
#endif
	case KVM_CAP_PPC_HTM:
		r = cpu_has_feature(CPU_FTR_TM_COMP) && hv_enabled;
		break;
	default:
		r = 0;
		break;
	}
	return r;

}


Input:
static bool handle_client_startup(PgSocket *client, PktHdr *pkt)
{
	const char *passwd;
	const uint8_t *key;
	bool ok;

	SBuf *sbuf = &client->sbuf;

	/* don't tolerate partial packets */
	if (incomplete_pkt(pkt)) {
		disconnect_client(client, true, "client sent partial pkt in startup phase");
		return false;
	}

	if (client->wait_for_welcome) {
		if  (finish_client_login(client)) {
			/* the packet was already parsed */
			sbuf_prepare_skip(sbuf, pkt->len);
			return true;
		} else
			return false;
	}

	switch (pkt->type) {
	case PKT_SSLREQ:
		slog_noise(client, "C: req SSL");
		slog_noise(client, "P: nak");

		/* reject SSL attempt */
		if (!sbuf_answer(&client->sbuf, "N", 1)) {
			disconnect_client(client, false, "failed to nak SSL");
			return false;
		}
		break;
	case PKT_STARTUP_V2:
		disconnect_client(client, true, "Old V2 protocol not supported");
		return false;
	case PKT_STARTUP:
		if (client->pool) {
			disconnect_client(client, true, "client re-sent startup pkt");
			return false;
		}

		if (!decide_startup_pool(client, pkt))
			return false;

		if (client->pool->db->admin) {
			if (!admin_pre_login(client))
				return false;
		}

		if (cf_auth_type <= AUTH_TRUST || client->own_user) {
			if (!finish_client_login(client))
				return false;
		} else {
			if (!send_client_authreq(client)) {
				disconnect_client(client, false, "failed to send auth req");
				return false;
			}
		}
		break;
	case 'p':		/* PasswordMessage */
		/* haven't requested it */
		if (cf_auth_type <= AUTH_TRUST) {
			disconnect_client(client, true, "unrequested passwd pkt");
			return false;
		}

		ok = mbuf_get_string(&pkt->data, &passwd);
		if (ok && check_client_passwd(client, passwd)) {
			if (!finish_client_login(client))
				return false;
		} else {
			disconnect_client(client, true, "Auth failed");
			return false;
		}
		break;
	case PKT_CANCEL:
		if (mbuf_avail_for_read(&pkt->data) == BACKENDKEY_LEN
		    && mbuf_get_bytes(&pkt->data, BACKENDKEY_LEN, &key))
		{
			memcpy(client->cancel_key, key, BACKENDKEY_LEN);
			accept_cancel_request(client);
		} else
			disconnect_client(client, false, "bad cancel request");
		return false;
	default:
		disconnect_client(client, false, "bad packet");
		return false;
	}
	sbuf_prepare_skip(sbuf, pkt->len);
	client->request_time = get_cached_time();
	return true;
}

static bool handle_client_startup(PgSocket *client, PktHdr *pkt)
{
	const char *passwd;
	const uint8_t *key;
	bool ok;

	SBuf *sbuf = &client->sbuf;

	/* don't tolerate partial packets */
	if (incomplete_pkt(pkt)) {
		disconnect_client(client, true, "client sent partial pkt in startup phase");
		return false;
	}

	if (client->wait_for_welcome) {
		if  (finish_client_login(client)) {
			/* the packet was already parsed */
			sbuf_prepare_skip(sbuf, pkt->len);
			return true;
		} else
			return false;
	}

	switch (pkt->type) {
	case PKT_SSLREQ:
		slog_noise(client, "C: req SSL");
		slog_noise(client, "P: nak");

		/* reject SSL attempt */
		if (!sbuf_answer(&client->sbuf, "N", 1)) {
			disconnect_client(client, false, "failed to nak SSL");
			return false;
		}
		break;
	case PKT_STARTUP_V2:
		disconnect_client(client, true, "Old V2 protocol not supported");
		return false;
	case PKT_STARTUP:
		if (client->pool) {
			disconnect_client(client, true, "client re-sent startup pkt");
			return false;
		}

		if (!decide_startup_pool(client, pkt))
			return false;

		if (client->pool->db->admin) {
			if (!admin_pre_login(client))
				return false;
		}

		if (cf_auth_type <= AUTH_TRUST || client->own_user) {
			if (!finish_client_login(client))
				return false;
		} else {
			if (!send_client_authreq(client)) {
				disconnect_client(client, false, "failed to send auth req");
				return false;
			}
		}
		break;
	case 'p':		/* PasswordMessage */
		/* too early */
		if (!client->auth_user) {
			disconnect_client(client, true, "client password pkt before startup packet");
			return false;
		}

		/* haven't requested it */
		if (cf_auth_type <= AUTH_TRUST) {
			disconnect_client(client, true, "unrequested passwd pkt");
			return false;
		}

		ok = mbuf_get_string(&pkt->data, &passwd);
		if (ok && check_client_passwd(client, passwd)) {
			if (!finish_client_login(client))
				return false;
		} else {
			disconnect_client(client, true, "Auth failed");
			return false;
		}
		break;
	case PKT_CANCEL:
		if (mbuf_avail_for_read(&pkt->data) == BACKENDKEY_LEN
		    && mbuf_get_bytes(&pkt->data, BACKENDKEY_LEN, &key))
		{
			memcpy(client->cancel_key, key, BACKENDKEY_LEN);
			accept_cancel_request(client);
		} else
			disconnect_client(client, false, "bad cancel request");
		return false;
	default:
		disconnect_client(client, false, "bad packet");
		return false;
	}
	sbuf_prepare_skip(sbuf, pkt->len);
	client->request_time = get_cached_time();
	return true;
}


Input:
static int nsv_read_chunk(AVFormatContext *s, int fill_header)
{
    NSVContext *nsv = s->priv_data;
    AVIOContext *pb = s->pb;
    AVStream *st[2] = {NULL, NULL};
    NSVStream *nst;
    AVPacket *pkt;
    int i, err = 0;
    uint8_t auxcount; /* number of aux metadata, also 4 bits of vsize */
    uint32_t vsize;
    uint16_t asize;
    uint16_t auxsize;

    if (nsv->ahead[0].data || nsv->ahead[1].data)
        return 0; //-1; /* hey! eat what you've in your plate first! */

null_chunk_retry:
    if (pb->eof_reached)
        return -1;

    for (i = 0; i < NSV_MAX_RESYNC_TRIES && nsv->state < NSV_FOUND_NSVS && !err; i++)
        err = nsv_resync(s);
    if (err < 0)
        return err;
    if (nsv->state == NSV_FOUND_NSVS)
        err = nsv_parse_NSVs_header(s);
    if (err < 0)
        return err;
    if (nsv->state != NSV_HAS_READ_NSVS && nsv->state != NSV_FOUND_BEEF)
        return -1;

    auxcount = avio_r8(pb);
    vsize = avio_rl16(pb);
    asize = avio_rl16(pb);
    vsize = (vsize << 4) | (auxcount >> 4);
    auxcount &= 0x0f;
    av_log(s, AV_LOG_TRACE, "NSV CHUNK %"PRIu8" aux, %"PRIu32" bytes video, %"PRIu16" bytes audio\n",
           auxcount, vsize, asize);
    /* skip aux stuff */
    for (i = 0; i < auxcount; i++) {
        uint32_t av_unused auxtag;
        auxsize = avio_rl16(pb);
        auxtag = avio_rl32(pb);
        avio_skip(pb, auxsize);
        vsize -= auxsize + sizeof(uint16_t) + sizeof(uint32_t); /* that's becoming brain-dead */
    }

    if (pb->eof_reached)
        return -1;
    if (!vsize && !asize) {
        nsv->state = NSV_UNSYNC;
        goto null_chunk_retry;
    }

    /* map back streams to v,a */
    if (s->nb_streams > 0)
        st[s->streams[0]->id] = s->streams[0];
    if (s->nb_streams > 1)
        st[s->streams[1]->id] = s->streams[1];

    if (vsize && st[NSV_ST_VIDEO]) {
        nst = st[NSV_ST_VIDEO]->priv_data;
        pkt = &nsv->ahead[NSV_ST_VIDEO];
        av_get_packet(pb, pkt, vsize);
        pkt->stream_index = st[NSV_ST_VIDEO]->index;//NSV_ST_VIDEO;
        pkt->dts = nst->frame_offset;
        pkt->flags |= nsv->state == NSV_HAS_READ_NSVS ? AV_PKT_FLAG_KEY : 0; /* keyframe only likely on a sync frame */
        for (i = 0; i < FFMIN(8, vsize); i++)
            av_log(s, AV_LOG_TRACE, "NSV video: [%d] = %02"PRIx8"\n",
                   i, pkt->data[i]);
    }
    if(st[NSV_ST_VIDEO])
        ((NSVStream*)st[NSV_ST_VIDEO]->priv_data)->frame_offset++;

    if (asize && st[NSV_ST_AUDIO]) {
        nst = st[NSV_ST_AUDIO]->priv_data;
        pkt = &nsv->ahead[NSV_ST_AUDIO];
        /* read raw audio specific header on the first audio chunk... */
        /* on ALL audio chunks ?? seems so! */
        if (asize && st[NSV_ST_AUDIO]->codecpar->codec_tag == MKTAG('P', 'C', 'M', ' ')/* && fill_header*/) {
            uint8_t bps;
            uint8_t channels;
            uint16_t samplerate;
            bps = avio_r8(pb);
            channels = avio_r8(pb);
            samplerate = avio_rl16(pb);
            if (!channels || !samplerate)
                return AVERROR_INVALIDDATA;
            asize-=4;
            av_log(s, AV_LOG_TRACE, "NSV RAWAUDIO: bps %"PRIu8", nchan %"PRIu8", srate %"PRIu16"\n",
                   bps, channels, samplerate);
            if (fill_header) {
                st[NSV_ST_AUDIO]->need_parsing = AVSTREAM_PARSE_NONE; /* we know everything */
                if (bps != 16) {
                    av_log(s, AV_LOG_TRACE, "NSV AUDIO bit/sample != 16 (%"PRIu8")!!!\n", bps);
                }
                bps /= channels; // ???
                if (bps == 8)
                    st[NSV_ST_AUDIO]->codecpar->codec_id = AV_CODEC_ID_PCM_U8;
                samplerate /= 4;/* UGH ??? XXX */
                channels = 1;
                st[NSV_ST_AUDIO]->codecpar->channels = channels;
                st[NSV_ST_AUDIO]->codecpar->sample_rate = samplerate;
                av_log(s, AV_LOG_TRACE, "NSV RAWAUDIO: bps %"PRIu8", nchan %"PRIu8", srate %"PRIu16"\n",
                       bps, channels, samplerate);
            }
        }
        av_get_packet(pb, pkt, asize);
        pkt->stream_index = st[NSV_ST_AUDIO]->index;//NSV_ST_AUDIO;
        pkt->flags |= nsv->state == NSV_HAS_READ_NSVS ? AV_PKT_FLAG_KEY : 0; /* keyframe only likely on a sync frame */
        if( nsv->state == NSV_HAS_READ_NSVS && st[NSV_ST_VIDEO] ) {
            /* on a nsvs frame we have new information on a/v sync */
            pkt->dts = (((NSVStream*)st[NSV_ST_VIDEO]->priv_data)->frame_offset-1);
            pkt->dts *= (int64_t)1000        * nsv->framerate.den;
            pkt->dts += (int64_t)nsv->avsync * nsv->framerate.num;
            av_log(s, AV_LOG_TRACE, "NSV AUDIO: sync:%"PRId16", dts:%"PRId64,
                   nsv->avsync, pkt->dts);
        }
        nst->frame_offset++;
    }

    nsv->state = NSV_UNSYNC;
    return 0;
}

static int nsv_read_chunk(AVFormatContext *s, int fill_header)
{
    NSVContext *nsv = s->priv_data;
    AVIOContext *pb = s->pb;
    AVStream *st[2] = {NULL, NULL};
    NSVStream *nst;
    AVPacket *pkt;
    int i, err = 0;
    uint8_t auxcount; /* number of aux metadata, also 4 bits of vsize */
    uint32_t vsize;
    uint16_t asize;
    uint16_t auxsize;
    int ret;

    if (nsv->ahead[0].data || nsv->ahead[1].data)
        return 0; //-1; /* hey! eat what you've in your plate first! */

null_chunk_retry:
    if (pb->eof_reached)
        return -1;

    for (i = 0; i < NSV_MAX_RESYNC_TRIES && nsv->state < NSV_FOUND_NSVS && !err; i++)
        err = nsv_resync(s);
    if (err < 0)
        return err;
    if (nsv->state == NSV_FOUND_NSVS)
        err = nsv_parse_NSVs_header(s);
    if (err < 0)
        return err;
    if (nsv->state != NSV_HAS_READ_NSVS && nsv->state != NSV_FOUND_BEEF)
        return -1;

    auxcount = avio_r8(pb);
    vsize = avio_rl16(pb);
    asize = avio_rl16(pb);
    vsize = (vsize << 4) | (auxcount >> 4);
    auxcount &= 0x0f;
    av_log(s, AV_LOG_TRACE, "NSV CHUNK %"PRIu8" aux, %"PRIu32" bytes video, %"PRIu16" bytes audio\n",
           auxcount, vsize, asize);
    /* skip aux stuff */
    for (i = 0; i < auxcount; i++) {
        uint32_t av_unused auxtag;
        auxsize = avio_rl16(pb);
        auxtag = avio_rl32(pb);
        avio_skip(pb, auxsize);
        vsize -= auxsize + sizeof(uint16_t) + sizeof(uint32_t); /* that's becoming brain-dead */
    }

    if (pb->eof_reached)
        return -1;
    if (!vsize && !asize) {
        nsv->state = NSV_UNSYNC;
        goto null_chunk_retry;
    }

    /* map back streams to v,a */
    if (s->nb_streams > 0)
        st[s->streams[0]->id] = s->streams[0];
    if (s->nb_streams > 1)
        st[s->streams[1]->id] = s->streams[1];

    if (vsize && st[NSV_ST_VIDEO]) {
        nst = st[NSV_ST_VIDEO]->priv_data;
        pkt = &nsv->ahead[NSV_ST_VIDEO];
        if ((ret = av_get_packet(pb, pkt, vsize)) < 0)
            return ret;
        pkt->stream_index = st[NSV_ST_VIDEO]->index;//NSV_ST_VIDEO;
        pkt->dts = nst->frame_offset;
        pkt->flags |= nsv->state == NSV_HAS_READ_NSVS ? AV_PKT_FLAG_KEY : 0; /* keyframe only likely on a sync frame */
        for (i = 0; i < FFMIN(8, vsize); i++)
            av_log(s, AV_LOG_TRACE, "NSV video: [%d] = %02"PRIx8"\n",
                   i, pkt->data[i]);
    }
    if(st[NSV_ST_VIDEO])
        ((NSVStream*)st[NSV_ST_VIDEO]->priv_data)->frame_offset++;

    if (asize && st[NSV_ST_AUDIO]) {
        nst = st[NSV_ST_AUDIO]->priv_data;
        pkt = &nsv->ahead[NSV_ST_AUDIO];
        /* read raw audio specific header on the first audio chunk... */
        /* on ALL audio chunks ?? seems so! */
        if (asize && st[NSV_ST_AUDIO]->codecpar->codec_tag == MKTAG('P', 'C', 'M', ' ')/* && fill_header*/) {
            uint8_t bps;
            uint8_t channels;
            uint16_t samplerate;
            bps = avio_r8(pb);
            channels = avio_r8(pb);
            samplerate = avio_rl16(pb);
            if (!channels || !samplerate)
                return AVERROR_INVALIDDATA;
            asize-=4;
            av_log(s, AV_LOG_TRACE, "NSV RAWAUDIO: bps %"PRIu8", nchan %"PRIu8", srate %"PRIu16"\n",
                   bps, channels, samplerate);
            if (fill_header) {
                st[NSV_ST_AUDIO]->need_parsing = AVSTREAM_PARSE_NONE; /* we know everything */
                if (bps != 16) {
                    av_log(s, AV_LOG_TRACE, "NSV AUDIO bit/sample != 16 (%"PRIu8")!!!\n", bps);
                }
                bps /= channels; // ???
                if (bps == 8)
                    st[NSV_ST_AUDIO]->codecpar->codec_id = AV_CODEC_ID_PCM_U8;
                samplerate /= 4;/* UGH ??? XXX */
                channels = 1;
                st[NSV_ST_AUDIO]->codecpar->channels = channels;
                st[NSV_ST_AUDIO]->codecpar->sample_rate = samplerate;
                av_log(s, AV_LOG_TRACE, "NSV RAWAUDIO: bps %"PRIu8", nchan %"PRIu8", srate %"PRIu16"\n",
                       bps, channels, samplerate);
            }
        }
        if ((ret = av_get_packet(pb, pkt, asize)) < 0)
            return ret;
        pkt->stream_index = st[NSV_ST_AUDIO]->index;//NSV_ST_AUDIO;
        pkt->flags |= nsv->state == NSV_HAS_READ_NSVS ? AV_PKT_FLAG_KEY : 0; /* keyframe only likely on a sync frame */
        if( nsv->state == NSV_HAS_READ_NSVS && st[NSV_ST_VIDEO] ) {
            /* on a nsvs frame we have new information on a/v sync */
            pkt->dts = (((NSVStream*)st[NSV_ST_VIDEO]->priv_data)->frame_offset-1);
            pkt->dts *= (int64_t)1000        * nsv->framerate.den;
            pkt->dts += (int64_t)nsv->avsync * nsv->framerate.num;
            av_log(s, AV_LOG_TRACE, "NSV AUDIO: sync:%"PRId16", dts:%"PRId64,
                   nsv->avsync, pkt->dts);
        }
        nst->frame_offset++;
    }

    nsv->state = NSV_UNSYNC;
    return 0;
}


Input:
_kdc_as_rep(kdc_request_t r,
	    krb5_data *reply,
	    const char *from,
	    struct sockaddr *from_addr,
	    int datagram_reply)
{
    krb5_context context = r->context;
    krb5_kdc_configuration *config = r->config;
    KDC_REQ *req = &r->req;
    KDC_REQ_BODY *b = NULL;
    AS_REP rep;
    KDCOptions f;
    krb5_enctype setype;
    krb5_error_code ret = 0;
    Key *skey;
    int found_pa = 0;
    int i, flags = HDB_F_FOR_AS_REQ;
    METHOD_DATA error_method;
    const PA_DATA *pa;

    memset(&rep, 0, sizeof(rep));
    error_method.len = 0;
    error_method.val = NULL;

    /*
     * Look for FAST armor and unwrap
     */
    ret = _kdc_fast_unwrap_request(r);
    if (ret) {
	_kdc_r_log(r, 0, "FAST unwrap request from %s failed: %d", from, ret);
	goto out;
    }

    b = &req->req_body;
    f = b->kdc_options;

    if (f.canonicalize)
	flags |= HDB_F_CANON;

    if(b->sname == NULL){
	ret = KRB5KRB_ERR_GENERIC;
	_kdc_set_e_text(r, "No server in request");
    } else{
	ret = _krb5_principalname2krb5_principal (context,
						  &r->server_princ,
						  *(b->sname),
						  b->realm);
	if (ret == 0)
	    ret = krb5_unparse_name(context, r->server_princ, &r->server_name);
    }
    if (ret) {
	kdc_log(context, config, 0,
		"AS-REQ malformed server name from %s", from);
	goto out;
    }
    if(b->cname == NULL){
	ret = KRB5KRB_ERR_GENERIC;
	_kdc_set_e_text(r, "No client in request");
    } else {
	ret = _krb5_principalname2krb5_principal (context,
						  &r->client_princ,
						  *(b->cname),
						  b->realm);
	if (ret)
	    goto out;

	ret = krb5_unparse_name(context, r->client_princ, &r->client_name);
    }
    if (ret) {
	kdc_log(context, config, 0,
		"AS-REQ malformed client name from %s", from);
	goto out;
    }

    kdc_log(context, config, 0, "AS-REQ %s from %s for %s",
	    r->client_name, from, r->server_name);

    /*
     *
     */

    if (_kdc_is_anonymous(context, r->client_princ)) {
	if (!_kdc_is_anon_request(b)) {
	    kdc_log(context, config, 0, "Anonymous ticket w/o anonymous flag");
	    ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
	    goto out;
	}
    } else if (_kdc_is_anon_request(b)) {
	kdc_log(context, config, 0,
		"Request for a anonymous ticket with non "
		"anonymous client name: %s", r->client_name);
	ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
	goto out;
    }

    /*
     *
     */

    ret = _kdc_db_fetch(context, config, r->client_princ,
			HDB_F_GET_CLIENT | flags, NULL,
			&r->clientdb, &r->client);
    if(ret == HDB_ERR_NOT_FOUND_HERE) {
	kdc_log(context, config, 5, "client %s does not have secrets at this KDC, need to proxy",
		r->client_name);
	goto out;
    } else if (ret == HDB_ERR_WRONG_REALM) {
	char *fixed_client_name = NULL;

	ret = krb5_unparse_name(context, r->client->entry.principal,
				&fixed_client_name);
	if (ret) {
	    goto out;
	}

	kdc_log(context, config, 0, "WRONG_REALM - %s -> %s",
		r->client_name, fixed_client_name);
	free(fixed_client_name);

	ret = _kdc_fast_mk_error(context, r,
				 &error_method,
				 r->armor_crypto,
				 &req->req_body,
				 KRB5_KDC_ERR_WRONG_REALM,
				 NULL,
				 r->server_princ,
				 NULL,
				 &r->client->entry.principal->realm,
				 NULL, NULL,
				 reply);
	goto out;
    } else if(ret){
	const char *msg = krb5_get_error_message(context, ret);
	kdc_log(context, config, 0, "UNKNOWN -- %s: %s", r->client_name, msg);
	krb5_free_error_message(context, msg);
	ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
	goto out;
    }
    ret = _kdc_db_fetch(context, config, r->server_princ,
			HDB_F_GET_SERVER|HDB_F_GET_KRBTGT | flags,
			NULL, NULL, &r->server);
    if(ret == HDB_ERR_NOT_FOUND_HERE) {
	kdc_log(context, config, 5, "target %s does not have secrets at this KDC, need to proxy",
		r->server_name);
	goto out;
    } else if(ret){
	const char *msg = krb5_get_error_message(context, ret);
	kdc_log(context, config, 0, "UNKNOWN -- %s: %s", r->server_name, msg);
	krb5_free_error_message(context, msg);
	ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
	goto out;
    }

    /*
     * Select a session enctype from the list of the crypto system
     * supported enctypes that is supported by the client and is one of
     * the enctype of the enctype of the service (likely krbtgt).
     *
     * The latter is used as a hint of what enctypes all KDC support,
     * to make sure a newer version of KDC won't generate a session
     * enctype that an older version of a KDC in the same realm can't
     * decrypt.
     */

    ret = _kdc_find_etype(context,
			  krb5_principal_is_krbtgt(context, r->server_princ) ?
			  config->tgt_use_strongest_session_key :
			  config->svc_use_strongest_session_key, FALSE,
			  r->client, b->etype.val, b->etype.len, &r->sessionetype,
			  NULL);
    if (ret) {
	kdc_log(context, config, 0,
		"Client (%s) from %s has no common enctypes with KDC "
		"to use for the session key",
		r->client_name, from);
	goto out;
    }

    /*
     * Pre-auth processing
     */

    if(req->padata){
	unsigned int n;

	log_patypes(context, config, req->padata);

	/* Check if preauth matching */

	for (n = 0; !found_pa && n < sizeof(pat) / sizeof(pat[0]); n++) {
	    if (pat[n].validate == NULL)
		continue;
	    if (r->armor_crypto == NULL && (pat[n].flags & PA_REQ_FAST))
		continue;

	    kdc_log(context, config, 5,
		    "Looking for %s pa-data -- %s", pat[n].name, r->client_name);
	    i = 0;
	    pa = _kdc_find_padata(req, &i, pat[n].type);
	    if (pa) {
		ret = pat[n].validate(r, pa);
		if (ret != 0) {
		    goto out;
		}
		kdc_log(context, config, 0,
			"%s pre-authentication succeeded -- %s",
			pat[n].name, r->client_name);
		found_pa = 1;
		r->et.flags.pre_authent = 1;
	    }
	}
    }

    if (found_pa == 0) {
	Key *ckey = NULL;
	size_t n;

	for (n = 0; n < sizeof(pat) / sizeof(pat[0]); n++) {
	    if ((pat[n].flags & PA_ANNOUNCE) == 0)
		continue;
	    ret = krb5_padata_add(context, &error_method,
				  pat[n].type, NULL, 0);
	    if (ret)
		goto out;
	}

	/*
	 * If there is a client key, send ETYPE_INFO{,2}
	 */
	ret = _kdc_find_etype(context,
			      config->preauth_use_strongest_session_key, TRUE,
			      r->client, b->etype.val, b->etype.len, NULL, &ckey);
	if (ret == 0) {

	    /*
	     * RFC4120 requires:
	     * - If the client only knows about old enctypes, then send
	     *   both info replies (we send 'info' first in the list).
	     * - If the client is 'modern', because it knows about 'new'
	     *   enctype types, then only send the 'info2' reply.
	     *
	     * Before we send the full list of etype-info data, we pick
	     * the client key we would have used anyway below, just pick
	     * that instead.
	     */

	    if (older_enctype(ckey->key.keytype)) {
		ret = get_pa_etype_info(context, config,
					&error_method, ckey);
		if (ret)
		    goto out;
	    }
	    ret = get_pa_etype_info2(context, config,
				     &error_method, ckey);
	    if (ret)
		goto out;
	}

	/*
	 * send requre preauth is its required or anon is requested,
	 * anon is today only allowed via preauth mechanisms.
	 */
	if (require_preauth_p(r) || _kdc_is_anon_request(b)) {
	    ret = KRB5KDC_ERR_PREAUTH_REQUIRED;
	    _kdc_set_e_text(r, "Need to use PA-ENC-TIMESTAMP/PA-PK-AS-REQ");
	    goto out;
	}

	if (ckey == NULL) {
	    ret = KRB5KDC_ERR_CLIENT_NOTYET;
	    _kdc_set_e_text(r, "Doesn't have a client key available");
	    goto out;
	}
	krb5_free_keyblock_contents(r->context,  &r->reply_key);
	ret = krb5_copy_keyblock_contents(r->context, &ckey->key, &r->reply_key);
	if (ret)
	    goto out;
    }

    if (r->clientdb->hdb_auth_status) {
	r->clientdb->hdb_auth_status(context, r->clientdb, r->client,
				     HDB_AUTH_SUCCESS);
    }

    /*
     * Verify flags after the user been required to prove its identity
     * with in a preauth mech.
     */

    ret = _kdc_check_access(context, config, r->client, r->client_name,
			    r->server, r->server_name,
			    req, &error_method);
    if(ret)
	goto out;

    /*
     * Select the best encryption type for the KDC with out regard to
     * the client since the client never needs to read that data.
     */

    ret = _kdc_get_preferred_key(context, config,
				 r->server, r->server_name,
				 &setype, &skey);
    if(ret)
	goto out;

    if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey
       || (_kdc_is_anon_request(b) && !config->allow_anonymous)) {
	ret = KRB5KDC_ERR_BADOPTION;
	_kdc_set_e_text(r, "Bad KDC options");
	goto out;
    }

    /*
     * Build reply
     */

    rep.pvno = 5;
    rep.msg_type = krb_as_rep;

    if (_kdc_is_anonymous(context, r->client_princ)) {
	Realm anon_realm=KRB5_ANON_REALM;
	ret = copy_Realm(&anon_realm, &rep.crealm);
    } else
	ret = copy_Realm(&r->client->entry.principal->realm, &rep.crealm);
    if (ret)
	goto out;
    ret = _krb5_principal2principalname(&rep.cname, r->client->entry.principal);
    if (ret)
	goto out;

    rep.ticket.tkt_vno = 5;
    ret = copy_Realm(&r->server->entry.principal->realm, &rep.ticket.realm);
    if (ret)
	goto out;
    _krb5_principal2principalname(&rep.ticket.sname,
				  r->server->entry.principal);
    /* java 1.6 expects the name to be the same type, lets allow that
     * uncomplicated name-types. */
#define CNT(sp,t) (((sp)->sname->name_type) == KRB5_NT_##t)
    if (CNT(b, UNKNOWN) || CNT(b, PRINCIPAL) || CNT(b, SRV_INST) || CNT(b, SRV_HST) || CNT(b, SRV_XHST))
	rep.ticket.sname.name_type = b->sname->name_type;
#undef CNT

    r->et.flags.initial = 1;
    if(r->client->entry.flags.forwardable && r->server->entry.flags.forwardable)
	r->et.flags.forwardable = f.forwardable;
    else if (f.forwardable) {
	_kdc_set_e_text(r, "Ticket may not be forwardable");
	ret = KRB5KDC_ERR_POLICY;
	goto out;
    }
    if(r->client->entry.flags.proxiable && r->server->entry.flags.proxiable)
	r->et.flags.proxiable = f.proxiable;
    else if (f.proxiable) {
	_kdc_set_e_text(r, "Ticket may not be proxiable");
	ret = KRB5KDC_ERR_POLICY;
	goto out;
    }
    if(r->client->entry.flags.postdate && r->server->entry.flags.postdate)
	r->et.flags.may_postdate = f.allow_postdate;
    else if (f.allow_postdate){
	_kdc_set_e_text(r, "Ticket may not be postdate");
	ret = KRB5KDC_ERR_POLICY;
	goto out;
    }

    /* check for valid set of addresses */
    if(!_kdc_check_addresses(context, config, b->addresses, from_addr)) {
	_kdc_set_e_text(r, "Bad address list in requested");
	ret = KRB5KRB_AP_ERR_BADADDR;
	goto out;
    }

    ret = copy_PrincipalName(&rep.cname, &r->et.cname);
    if (ret)
	goto out;
    ret = copy_Realm(&rep.crealm, &r->et.crealm);
    if (ret)
	goto out;

    {
	time_t start;
	time_t t;

	start = r->et.authtime = kdc_time;

	if(f.postdated && req->req_body.from){
	    ALLOC(r->et.starttime);
	    start = *r->et.starttime = *req->req_body.from;
	    r->et.flags.invalid = 1;
	    r->et.flags.postdated = 1; /* XXX ??? */
	}
	_kdc_fix_time(&b->till);
	t = *b->till;

	/* be careful not overflowing */

	if(r->client->entry.max_life)
	    t = start + min(t - start, *r->client->entry.max_life);
	if(r->server->entry.max_life)
	    t = start + min(t - start, *r->server->entry.max_life);
#if 0
	t = min(t, start + realm->max_life);
#endif
	r->et.endtime = t;
	if(f.renewable_ok && r->et.endtime < *b->till){
	    f.renewable = 1;
	    if(b->rtime == NULL){
		ALLOC(b->rtime);
		*b->rtime = 0;
	    }
	    if(*b->rtime < *b->till)
		*b->rtime = *b->till;
	}
	if(f.renewable && b->rtime){
	    t = *b->rtime;
	    if(t == 0)
		t = MAX_TIME;
	    if(r->client->entry.max_renew)
		t = start + min(t - start, *r->client->entry.max_renew);
	    if(r->server->entry.max_renew)
		t = start + min(t - start, *r->server->entry.max_renew);
#if 0
	    t = min(t, start + realm->max_renew);
#endif
	    ALLOC(r->et.renew_till);
	    *r->et.renew_till = t;
	    r->et.flags.renewable = 1;
	}
    }

    if (_kdc_is_anon_request(b))
	r->et.flags.anonymous = 1;

    if(b->addresses){
	ALLOC(r->et.caddr);
	copy_HostAddresses(b->addresses, r->et.caddr);
    }

    r->et.transited.tr_type = DOMAIN_X500_COMPRESS;
    krb5_data_zero(&r->et.transited.contents);

    /* The MIT ASN.1 library (obviously) doesn't tell lengths encoded
     * as 0 and as 0x80 (meaning indefinite length) apart, and is thus
     * incapable of correctly decoding SEQUENCE OF's of zero length.
     *
     * To fix this, always send at least one no-op last_req
     *
     * If there's a pw_end or valid_end we will use that,
     * otherwise just a dummy lr.
     */
    r->ek.last_req.val = malloc(2 * sizeof(*r->ek.last_req.val));
    if (r->ek.last_req.val == NULL) {
	ret = ENOMEM;
	goto out;
    }
    r->ek.last_req.len = 0;
    if (r->client->entry.pw_end
	&& (config->kdc_warn_pwexpire == 0
	    || kdc_time + config->kdc_warn_pwexpire >= *r->client->entry.pw_end)) {
	r->ek.last_req.val[r->ek.last_req.len].lr_type  = LR_PW_EXPTIME;
	r->ek.last_req.val[r->ek.last_req.len].lr_value = *r->client->entry.pw_end;
	++r->ek.last_req.len;
    }
    if (r->client->entry.valid_end) {
	r->ek.last_req.val[r->ek.last_req.len].lr_type  = LR_ACCT_EXPTIME;
	r->ek.last_req.val[r->ek.last_req.len].lr_value = *r->client->entry.valid_end;
	++r->ek.last_req.len;
    }
    if (r->ek.last_req.len == 0) {
	r->ek.last_req.val[r->ek.last_req.len].lr_type  = LR_NONE;
	r->ek.last_req.val[r->ek.last_req.len].lr_value = 0;
	++r->ek.last_req.len;
    }
    r->ek.nonce = b->nonce;
    if (r->client->entry.valid_end || r->client->entry.pw_end) {
	ALLOC(r->ek.key_expiration);
	if (r->client->entry.valid_end) {
	    if (r->client->entry.pw_end)
		*r->ek.key_expiration = min(*r->client->entry.valid_end,
					 *r->client->entry.pw_end);
	    else
		*r->ek.key_expiration = *r->client->entry.valid_end;
	} else
	    *r->ek.key_expiration = *r->client->entry.pw_end;
    } else
	r->ek.key_expiration = NULL;
    r->ek.flags = r->et.flags;
    r->ek.authtime = r->et.authtime;
    if (r->et.starttime) {
	ALLOC(r->ek.starttime);
	*r->ek.starttime = *r->et.starttime;
    }
    r->ek.endtime = r->et.endtime;
    if (r->et.renew_till) {
	ALLOC(r->ek.renew_till);
	*r->ek.renew_till = *r->et.renew_till;
    }
    ret = copy_Realm(&rep.ticket.realm, &r->ek.srealm);
    if (ret)
	goto out;
    ret = copy_PrincipalName(&rep.ticket.sname, &r->ek.sname);
    if (ret)
	goto out;
    if(r->et.caddr){
	ALLOC(r->ek.caddr);
	copy_HostAddresses(r->et.caddr, r->ek.caddr);
    }

    /*
     * Check and session and reply keys
     */

    if (r->session_key.keytype == ETYPE_NULL) {
	ret = krb5_generate_random_keyblock(context, r->sessionetype, &r->session_key);
	if (ret)
	    goto out;
    }

    if (r->reply_key.keytype == ETYPE_NULL) {
	_kdc_set_e_text(r, "Client have no reply key");
	ret = KRB5KDC_ERR_CLIENT_NOTYET;
	goto out;
    }

    ret = copy_EncryptionKey(&r->session_key, &r->et.key);
    if (ret)
	goto out;

    ret = copy_EncryptionKey(&r->session_key, &r->ek.key);
    if (ret)
	goto out;

    if (r->outpadata.len) {

	ALLOC(rep.padata);
	if (rep.padata == NULL) {
	    ret = ENOMEM;
	    goto out;
	}
	ret = copy_METHOD_DATA(&r->outpadata, rep.padata);
	if (ret)
	    goto out;
    }

    /* Add the PAC */
    if (send_pac_p(context, req)) {
	generate_pac(r, skey);
    }

    _kdc_log_timestamp(context, config, "AS-REQ", r->et.authtime, r->et.starttime,
		       r->et.endtime, r->et.renew_till);

    /* do this as the last thing since this signs the EncTicketPart */
    ret = _kdc_add_KRB5SignedPath(context,
				  config,
				  r->server,
				  setype,
				  r->client->entry.principal,
				  NULL,
				  NULL,
				  &r->et);
    if (ret)
	goto out;

    log_as_req(context, config, r->reply_key.keytype, setype, b);

    /*
     * We always say we support FAST/enc-pa-rep
     */

    r->et.flags.enc_pa_rep = r->ek.flags.enc_pa_rep = 1;

    /*
     * Add REQ_ENC_PA_REP if client supports it
     */

    i = 0;
    pa = _kdc_find_padata(req, &i, KRB5_PADATA_REQ_ENC_PA_REP);
    if (pa) {

	ret = add_enc_pa_rep(r);
	if (ret) {
	    const char *msg = krb5_get_error_message(r->context, ret);
	    _kdc_r_log(r, 0, "add_enc_pa_rep failed: %s: %d", msg, ret);
	    krb5_free_error_message(r->context, msg);
	    goto out;
	}
    }

    /*
     *
     */

    ret = _kdc_encode_reply(context, config,
			    r->armor_crypto, req->req_body.nonce,
			    &rep, &r->et, &r->ek, setype, r->server->entry.kvno,
			    &skey->key, r->client->entry.kvno,
			    &r->reply_key, 0, &r->e_text, reply);
    if (ret)
	goto out;

    /*
     * Check if message too large
     */
    if (datagram_reply && reply->length > config->max_datagram_reply_length) {
	krb5_data_free(reply);
	ret = KRB5KRB_ERR_RESPONSE_TOO_BIG;
	_kdc_set_e_text(r, "Reply packet too large");
    }

out:
    free_AS_REP(&rep);

    /*
     * In case of a non proxy error, build an error message.
     */
    if(ret != 0 && ret != HDB_ERR_NOT_FOUND_HERE && reply->length == 0) {
	ret = _kdc_fast_mk_error(context, r,
				 &error_method,
				 r->armor_crypto,
				 &req->req_body,
				 ret, r->e_text,
				 r->server_princ,
				 &r->client_princ->name,
				 &r->client_princ->realm,
				 NULL, NULL,
				 reply);
	if (ret)
	    goto out2;
    }
out2:
    free_EncTicketPart(&r->et);
    free_EncKDCRepPart(&r->ek);
    free_KDCFastState(&r->fast);

    if (error_method.len)
	free_METHOD_DATA(&error_method);
    if (r->outpadata.len)
	free_METHOD_DATA(&r->outpadata);
    if (r->client_princ) {
	krb5_free_principal(context, r->client_princ);
	r->client_princ = NULL;
    }
    if (r->client_name) {
	free(r->client_name);
	r->client_name = NULL;
    }
    if (r->server_princ){
	krb5_free_principal(context, r->server_princ);
	r->server_princ = NULL;
    }
    if (r->server_name) {
	free(r->server_name);
	r->server_name = NULL;
    }
    if (r->client)
	_kdc_free_ent(context, r->client);
    if (r->server)
	_kdc_free_ent(context, r->server);
    if (r->armor_crypto) {
	krb5_crypto_destroy(r->context, r->armor_crypto);
	r->armor_crypto = NULL;
    }
    krb5_free_keyblock_contents(r->context, &r->reply_key);
    krb5_free_keyblock_contents(r->context, &r->session_key);
    return ret;
}

_kdc_as_rep(kdc_request_t r,
	    krb5_data *reply,
	    const char *from,
	    struct sockaddr *from_addr,
	    int datagram_reply)
{
    krb5_context context = r->context;
    krb5_kdc_configuration *config = r->config;
    KDC_REQ *req = &r->req;
    KDC_REQ_BODY *b = NULL;
    AS_REP rep;
    KDCOptions f;
    krb5_enctype setype;
    krb5_error_code ret = 0;
    Key *skey;
    int found_pa = 0;
    int i, flags = HDB_F_FOR_AS_REQ;
    METHOD_DATA error_method;
    const PA_DATA *pa;

    memset(&rep, 0, sizeof(rep));
    error_method.len = 0;
    error_method.val = NULL;

    /*
     * Look for FAST armor and unwrap
     */
    ret = _kdc_fast_unwrap_request(r);
    if (ret) {
	_kdc_r_log(r, 0, "FAST unwrap request from %s failed: %d", from, ret);
	goto out;
    }

    b = &req->req_body;
    f = b->kdc_options;

    if (f.canonicalize)
	flags |= HDB_F_CANON;

    if(b->sname == NULL){
	ret = KRB5KRB_ERR_GENERIC;
	_kdc_set_e_text(r, "No server in request");
    } else{
	ret = _krb5_principalname2krb5_principal (context,
						  &r->server_princ,
						  *(b->sname),
						  b->realm);
	if (ret == 0)
	    ret = krb5_unparse_name(context, r->server_princ, &r->server_name);
    }
    if (ret) {
	kdc_log(context, config, 0,
		"AS-REQ malformed server name from %s", from);
	goto out;
    }
    if(b->cname == NULL){
	ret = KRB5KRB_ERR_GENERIC;
	_kdc_set_e_text(r, "No client in request");
    } else {
	ret = _krb5_principalname2krb5_principal (context,
						  &r->client_princ,
						  *(b->cname),
						  b->realm);
	if (ret)
	    goto out;

	ret = krb5_unparse_name(context, r->client_princ, &r->client_name);
    }
    if (ret) {
	kdc_log(context, config, 0,
		"AS-REQ malformed client name from %s", from);
	goto out;
    }

    kdc_log(context, config, 0, "AS-REQ %s from %s for %s",
	    r->client_name, from, r->server_name);

    /*
     *
     */

    if (_kdc_is_anonymous(context, r->client_princ)) {
	if (!_kdc_is_anon_request(b)) {
	    kdc_log(context, config, 0, "Anonymous ticket w/o anonymous flag");
	    ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
	    goto out;
	}
    } else if (_kdc_is_anon_request(b)) {
	kdc_log(context, config, 0,
		"Request for a anonymous ticket with non "
		"anonymous client name: %s", r->client_name);
	ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
	goto out;
    }

    /*
     *
     */

    ret = _kdc_db_fetch(context, config, r->client_princ,
			HDB_F_GET_CLIENT | flags, NULL,
			&r->clientdb, &r->client);
    if(ret == HDB_ERR_NOT_FOUND_HERE) {
	kdc_log(context, config, 5, "client %s does not have secrets at this KDC, need to proxy",
		r->client_name);
	goto out;
    } else if (ret == HDB_ERR_WRONG_REALM) {
	char *fixed_client_name = NULL;

	ret = krb5_unparse_name(context, r->client->entry.principal,
				&fixed_client_name);
	if (ret) {
	    goto out;
	}

	kdc_log(context, config, 0, "WRONG_REALM - %s -> %s",
		r->client_name, fixed_client_name);
	free(fixed_client_name);

	ret = _kdc_fast_mk_error(context, r,
				 &error_method,
				 r->armor_crypto,
				 &req->req_body,
				 KRB5_KDC_ERR_WRONG_REALM,
				 NULL,
				 r->server_princ,
				 NULL,
				 &r->client->entry.principal->realm,
				 NULL, NULL,
				 reply);
	goto out;
    } else if(ret){
	const char *msg = krb5_get_error_message(context, ret);
	kdc_log(context, config, 0, "UNKNOWN -- %s: %s", r->client_name, msg);
	krb5_free_error_message(context, msg);
	ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
	goto out;
    }
    ret = _kdc_db_fetch(context, config, r->server_princ,
			HDB_F_GET_SERVER|HDB_F_GET_KRBTGT | flags,
			NULL, NULL, &r->server);
    if(ret == HDB_ERR_NOT_FOUND_HERE) {
	kdc_log(context, config, 5, "target %s does not have secrets at this KDC, need to proxy",
		r->server_name);
	goto out;
    } else if(ret){
	const char *msg = krb5_get_error_message(context, ret);
	kdc_log(context, config, 0, "UNKNOWN -- %s: %s", r->server_name, msg);
	krb5_free_error_message(context, msg);
	ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
	goto out;
    }

    /*
     * Select a session enctype from the list of the crypto system
     * supported enctypes that is supported by the client and is one of
     * the enctype of the enctype of the service (likely krbtgt).
     *
     * The latter is used as a hint of what enctypes all KDC support,
     * to make sure a newer version of KDC won't generate a session
     * enctype that an older version of a KDC in the same realm can't
     * decrypt.
     */

    ret = _kdc_find_etype(context,
			  krb5_principal_is_krbtgt(context, r->server_princ) ?
			  config->tgt_use_strongest_session_key :
			  config->svc_use_strongest_session_key, FALSE,
			  r->client, b->etype.val, b->etype.len, &r->sessionetype,
			  NULL);
    if (ret) {
	kdc_log(context, config, 0,
		"Client (%s) from %s has no common enctypes with KDC "
		"to use for the session key",
		r->client_name, from);
	goto out;
    }

    /*
     * Pre-auth processing
     */

    if(req->padata){
	unsigned int n;

	log_patypes(context, config, req->padata);

	/* Check if preauth matching */

	for (n = 0; !found_pa && n < sizeof(pat) / sizeof(pat[0]); n++) {
	    if (pat[n].validate == NULL)
		continue;
	    if (r->armor_crypto == NULL && (pat[n].flags & PA_REQ_FAST))
		continue;

	    kdc_log(context, config, 5,
		    "Looking for %s pa-data -- %s", pat[n].name, r->client_name);
	    i = 0;
	    pa = _kdc_find_padata(req, &i, pat[n].type);
	    if (pa) {
		ret = pat[n].validate(r, pa);
		if (ret != 0) {
		    goto out;
		}
		kdc_log(context, config, 0,
			"%s pre-authentication succeeded -- %s",
			pat[n].name, r->client_name);
		found_pa = 1;
		r->et.flags.pre_authent = 1;
	    }
	}
    }

    if (found_pa == 0) {
	Key *ckey = NULL;
	size_t n;

	for (n = 0; n < sizeof(pat) / sizeof(pat[0]); n++) {
	    if ((pat[n].flags & PA_ANNOUNCE) == 0)
		continue;
	    ret = krb5_padata_add(context, &error_method,
				  pat[n].type, NULL, 0);
	    if (ret)
		goto out;
	}

	/*
	 * If there is a client key, send ETYPE_INFO{,2}
	 */
	ret = _kdc_find_etype(context,
			      config->preauth_use_strongest_session_key, TRUE,
			      r->client, b->etype.val, b->etype.len, NULL, &ckey);
	if (ret == 0) {

	    /*
	     * RFC4120 requires:
	     * - If the client only knows about old enctypes, then send
	     *   both info replies (we send 'info' first in the list).
	     * - If the client is 'modern', because it knows about 'new'
	     *   enctype types, then only send the 'info2' reply.
	     *
	     * Before we send the full list of etype-info data, we pick
	     * the client key we would have used anyway below, just pick
	     * that instead.
	     */

	    if (older_enctype(ckey->key.keytype)) {
		ret = get_pa_etype_info(context, config,
					&error_method, ckey);
		if (ret)
		    goto out;
	    }
	    ret = get_pa_etype_info2(context, config,
				     &error_method, ckey);
	    if (ret)
		goto out;
	}

	/*
	 * send requre preauth is its required or anon is requested,
	 * anon is today only allowed via preauth mechanisms.
	 */
	if (require_preauth_p(r) || _kdc_is_anon_request(b)) {
	    ret = KRB5KDC_ERR_PREAUTH_REQUIRED;
	    _kdc_set_e_text(r, "Need to use PA-ENC-TIMESTAMP/PA-PK-AS-REQ");
	    goto out;
	}

	if (ckey == NULL) {
	    ret = KRB5KDC_ERR_CLIENT_NOTYET;
	    _kdc_set_e_text(r, "Doesn't have a client key available");
	    goto out;
	}
	krb5_free_keyblock_contents(r->context,  &r->reply_key);
	ret = krb5_copy_keyblock_contents(r->context, &ckey->key, &r->reply_key);
	if (ret)
	    goto out;
    }

    if (r->clientdb->hdb_auth_status) {
	r->clientdb->hdb_auth_status(context, r->clientdb, r->client,
				     HDB_AUTH_SUCCESS);
    }

    /*
     * Verify flags after the user been required to prove its identity
     * with in a preauth mech.
     */

    ret = _kdc_check_access(context, config, r->client, r->client_name,
			    r->server, r->server_name,
			    req, &error_method);
    if(ret)
	goto out;

    /*
     * Select the best encryption type for the KDC with out regard to
     * the client since the client never needs to read that data.
     */

    ret = _kdc_get_preferred_key(context, config,
				 r->server, r->server_name,
				 &setype, &skey);
    if(ret)
	goto out;

    if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey
       || (_kdc_is_anon_request(b) && !config->allow_anonymous)) {
	ret = KRB5KDC_ERR_BADOPTION;
	_kdc_set_e_text(r, "Bad KDC options");
	goto out;
    }

    /*
     * Build reply
     */

    rep.pvno = 5;
    rep.msg_type = krb_as_rep;

    if (_kdc_is_anonymous(context, r->client_princ)) {
	Realm anon_realm=KRB5_ANON_REALM;
	ret = copy_Realm(&anon_realm, &rep.crealm);
    } else
	ret = copy_Realm(&r->client->entry.principal->realm, &rep.crealm);
    if (ret)
	goto out;
    ret = _krb5_principal2principalname(&rep.cname, r->client->entry.principal);
    if (ret)
	goto out;

    rep.ticket.tkt_vno = 5;
    ret = copy_Realm(&r->server->entry.principal->realm, &rep.ticket.realm);
    if (ret)
	goto out;
    _krb5_principal2principalname(&rep.ticket.sname,
				  r->server->entry.principal);
    /* java 1.6 expects the name to be the same type, lets allow that
     * uncomplicated name-types. */
#define CNT(sp,t) (((sp)->sname->name_type) == KRB5_NT_##t)
    if (CNT(b, UNKNOWN) || CNT(b, PRINCIPAL) || CNT(b, SRV_INST) || CNT(b, SRV_HST) || CNT(b, SRV_XHST))
	rep.ticket.sname.name_type = b->sname->name_type;
#undef CNT

    r->et.flags.initial = 1;
    if(r->client->entry.flags.forwardable && r->server->entry.flags.forwardable)
	r->et.flags.forwardable = f.forwardable;
    else if (f.forwardable) {
	_kdc_set_e_text(r, "Ticket may not be forwardable");
	ret = KRB5KDC_ERR_POLICY;
	goto out;
    }
    if(r->client->entry.flags.proxiable && r->server->entry.flags.proxiable)
	r->et.flags.proxiable = f.proxiable;
    else if (f.proxiable) {
	_kdc_set_e_text(r, "Ticket may not be proxiable");
	ret = KRB5KDC_ERR_POLICY;
	goto out;
    }
    if(r->client->entry.flags.postdate && r->server->entry.flags.postdate)
	r->et.flags.may_postdate = f.allow_postdate;
    else if (f.allow_postdate){
	_kdc_set_e_text(r, "Ticket may not be postdate");
	ret = KRB5KDC_ERR_POLICY;
	goto out;
    }

    /* check for valid set of addresses */
    if(!_kdc_check_addresses(context, config, b->addresses, from_addr)) {
	_kdc_set_e_text(r, "Bad address list in requested");
	ret = KRB5KRB_AP_ERR_BADADDR;
	goto out;
    }

    ret = copy_PrincipalName(&rep.cname, &r->et.cname);
    if (ret)
	goto out;
    ret = copy_Realm(&rep.crealm, &r->et.crealm);
    if (ret)
	goto out;

    {
	time_t start;
	time_t t;

	start = r->et.authtime = kdc_time;

	if(f.postdated && req->req_body.from){
	    ALLOC(r->et.starttime);
	    start = *r->et.starttime = *req->req_body.from;
	    r->et.flags.invalid = 1;
	    r->et.flags.postdated = 1; /* XXX ??? */
	}
	_kdc_fix_time(&b->till);
	t = *b->till;

	/* be careful not overflowing */

	if(r->client->entry.max_life)
	    t = start + min(t - start, *r->client->entry.max_life);
	if(r->server->entry.max_life)
	    t = start + min(t - start, *r->server->entry.max_life);
#if 0
	t = min(t, start + realm->max_life);
#endif
	r->et.endtime = t;
	if(f.renewable_ok && r->et.endtime < *b->till){
	    f.renewable = 1;
	    if(b->rtime == NULL){
		ALLOC(b->rtime);
		*b->rtime = 0;
	    }
	    if(*b->rtime < *b->till)
		*b->rtime = *b->till;
	}
	if(f.renewable && b->rtime){
	    t = *b->rtime;
	    if(t == 0)
		t = MAX_TIME;
	    if(r->client->entry.max_renew)
		t = start + min(t - start, *r->client->entry.max_renew);
	    if(r->server->entry.max_renew)
		t = start + min(t - start, *r->server->entry.max_renew);
#if 0
	    t = min(t, start + realm->max_renew);
#endif
	    ALLOC(r->et.renew_till);
	    *r->et.renew_till = t;
	    r->et.flags.renewable = 1;
	}
    }

    if (_kdc_is_anon_request(b))
	r->et.flags.anonymous = 1;

    if(b->addresses){
	ALLOC(r->et.caddr);
	copy_HostAddresses(b->addresses, r->et.caddr);
    }

    r->et.transited.tr_type = DOMAIN_X500_COMPRESS;
    krb5_data_zero(&r->et.transited.contents);

    /* The MIT ASN.1 library (obviously) doesn't tell lengths encoded
     * as 0 and as 0x80 (meaning indefinite length) apart, and is thus
     * incapable of correctly decoding SEQUENCE OF's of zero length.
     *
     * To fix this, always send at least one no-op last_req
     *
     * If there's a pw_end or valid_end we will use that,
     * otherwise just a dummy lr.
     */
    r->ek.last_req.val = malloc(2 * sizeof(*r->ek.last_req.val));
    if (r->ek.last_req.val == NULL) {
	ret = ENOMEM;
	goto out;
    }
    r->ek.last_req.len = 0;
    if (r->client->entry.pw_end
	&& (config->kdc_warn_pwexpire == 0
	    || kdc_time + config->kdc_warn_pwexpire >= *r->client->entry.pw_end)) {
	r->ek.last_req.val[r->ek.last_req.len].lr_type  = LR_PW_EXPTIME;
	r->ek.last_req.val[r->ek.last_req.len].lr_value = *r->client->entry.pw_end;
	++r->ek.last_req.len;
    }
    if (r->client->entry.valid_end) {
	r->ek.last_req.val[r->ek.last_req.len].lr_type  = LR_ACCT_EXPTIME;
	r->ek.last_req.val[r->ek.last_req.len].lr_value = *r->client->entry.valid_end;
	++r->ek.last_req.len;
    }
    if (r->ek.last_req.len == 0) {
	r->ek.last_req.val[r->ek.last_req.len].lr_type  = LR_NONE;
	r->ek.last_req.val[r->ek.last_req.len].lr_value = 0;
	++r->ek.last_req.len;
    }
    r->ek.nonce = b->nonce;
    if (r->client->entry.valid_end || r->client->entry.pw_end) {
	ALLOC(r->ek.key_expiration);
	if (r->client->entry.valid_end) {
	    if (r->client->entry.pw_end)
		*r->ek.key_expiration = min(*r->client->entry.valid_end,
					 *r->client->entry.pw_end);
	    else
		*r->ek.key_expiration = *r->client->entry.valid_end;
	} else
	    *r->ek.key_expiration = *r->client->entry.pw_end;
    } else
	r->ek.key_expiration = NULL;
    r->ek.flags = r->et.flags;
    r->ek.authtime = r->et.authtime;
    if (r->et.starttime) {
	ALLOC(r->ek.starttime);
	*r->ek.starttime = *r->et.starttime;
    }
    r->ek.endtime = r->et.endtime;
    if (r->et.renew_till) {
	ALLOC(r->ek.renew_till);
	*r->ek.renew_till = *r->et.renew_till;
    }
    ret = copy_Realm(&rep.ticket.realm, &r->ek.srealm);
    if (ret)
	goto out;
    ret = copy_PrincipalName(&rep.ticket.sname, &r->ek.sname);
    if (ret)
	goto out;
    if(r->et.caddr){
	ALLOC(r->ek.caddr);
	copy_HostAddresses(r->et.caddr, r->ek.caddr);
    }

    /*
     * Check and session and reply keys
     */

    if (r->session_key.keytype == ETYPE_NULL) {
	ret = krb5_generate_random_keyblock(context, r->sessionetype, &r->session_key);
	if (ret)
	    goto out;
    }

    if (r->reply_key.keytype == ETYPE_NULL) {
	_kdc_set_e_text(r, "Client have no reply key");
	ret = KRB5KDC_ERR_CLIENT_NOTYET;
	goto out;
    }

    ret = copy_EncryptionKey(&r->session_key, &r->et.key);
    if (ret)
	goto out;

    ret = copy_EncryptionKey(&r->session_key, &r->ek.key);
    if (ret)
	goto out;

    if (r->outpadata.len) {

	ALLOC(rep.padata);
	if (rep.padata == NULL) {
	    ret = ENOMEM;
	    goto out;
	}
	ret = copy_METHOD_DATA(&r->outpadata, rep.padata);
	if (ret)
	    goto out;
    }

    /* Add the PAC */
    if (send_pac_p(context, req)) {
	generate_pac(r, skey);
    }

    _kdc_log_timestamp(context, config, "AS-REQ", r->et.authtime, r->et.starttime,
		       r->et.endtime, r->et.renew_till);

    /* do this as the last thing since this signs the EncTicketPart */
    ret = _kdc_add_KRB5SignedPath(context,
				  config,
				  r->server,
				  setype,
				  r->client->entry.principal,
				  NULL,
				  NULL,
				  &r->et);
    if (ret)
	goto out;

    log_as_req(context, config, r->reply_key.keytype, setype, b);

    /*
     * We always say we support FAST/enc-pa-rep
     */

    r->et.flags.enc_pa_rep = r->ek.flags.enc_pa_rep = 1;

    /*
     * Add REQ_ENC_PA_REP if client supports it
     */

    i = 0;
    pa = _kdc_find_padata(req, &i, KRB5_PADATA_REQ_ENC_PA_REP);
    if (pa) {

	ret = add_enc_pa_rep(r);
	if (ret) {
	    const char *msg = krb5_get_error_message(r->context, ret);
	    _kdc_r_log(r, 0, "add_enc_pa_rep failed: %s: %d", msg, ret);
	    krb5_free_error_message(r->context, msg);
	    goto out;
	}
    }

    /*
     *
     */

    ret = _kdc_encode_reply(context, config,
			    r->armor_crypto, req->req_body.nonce,
			    &rep, &r->et, &r->ek, setype, r->server->entry.kvno,
			    &skey->key, r->client->entry.kvno,
			    &r->reply_key, 0, &r->e_text, reply);
    if (ret)
	goto out;

    /*
     * Check if message too large
     */
    if (datagram_reply && reply->length > config->max_datagram_reply_length) {
	krb5_data_free(reply);
	ret = KRB5KRB_ERR_RESPONSE_TOO_BIG;
	_kdc_set_e_text(r, "Reply packet too large");
    }

out:
    free_AS_REP(&rep);

    /*
     * In case of a non proxy error, build an error message.
     */
    if (ret != 0 && ret != HDB_ERR_NOT_FOUND_HERE && reply->length == 0) {
	ret = _kdc_fast_mk_error(context, r,
				 &error_method,
				 r->armor_crypto,
				 &req->req_body,
				 ret, r->e_text,
				 r->server_princ,
				 r->client_princ ?
                                     &r->client_princ->name : NULL,
				 r->client_princ ?
                                     &r->client_princ->realm : NULL,
				 NULL, NULL,
				 reply);
	if (ret)
	    goto out2;
    }
out2:
    free_EncTicketPart(&r->et);
    free_EncKDCRepPart(&r->ek);
    free_KDCFastState(&r->fast);

    if (error_method.len)
	free_METHOD_DATA(&error_method);
    if (r->outpadata.len)
	free_METHOD_DATA(&r->outpadata);
    if (r->client_princ) {
	krb5_free_principal(context, r->client_princ);
	r->client_princ = NULL;
    }
    if (r->client_name) {
	free(r->client_name);
	r->client_name = NULL;
    }
    if (r->server_princ){
	krb5_free_principal(context, r->server_princ);
	r->server_princ = NULL;
    }
    if (r->server_name) {
	free(r->server_name);
	r->server_name = NULL;
    }
    if (r->client)
	_kdc_free_ent(context, r->client);
    if (r->server)
	_kdc_free_ent(context, r->server);
    if (r->armor_crypto) {
	krb5_crypto_destroy(r->context, r->armor_crypto);
	r->armor_crypto = NULL;
    }
    krb5_free_keyblock_contents(r->context, &r->reply_key);
    krb5_free_keyblock_contents(r->context, &r->session_key);
    return ret;
}


Input:
formUpdateBuffer(Anchor *a, Buffer *buf, FormItemList *form)
{
    Buffer save;
    char *p;
    int spos, epos, rows, c_rows, pos, col = 0;
    Line *l;

    copyBuffer(&save, buf);
    gotoLine(buf, a->start.line);
    switch (form->type) {
    case FORM_TEXTAREA:
    case FORM_INPUT_TEXT:
    case FORM_INPUT_FILE:
    case FORM_INPUT_PASSWORD:
    case FORM_INPUT_CHECKBOX:
    case FORM_INPUT_RADIO:
#ifdef MENU_SELECT
    case FORM_SELECT:
#endif				/* MENU_SELECT */
	spos = a->start.pos;
	epos = a->end.pos;
	break;
    default:
	spos = a->start.pos + 1;
	epos = a->end.pos - 1;
    }
    switch (form->type) {
    case FORM_INPUT_CHECKBOX:
    case FORM_INPUT_RADIO:
	if (buf->currentLine == NULL ||
	    spos >= buf->currentLine->len || spos < 0)
	    break;
	if (form->checked)
	    buf->currentLine->lineBuf[spos] = '*';
	else
	    buf->currentLine->lineBuf[spos] = ' ';
	break;
    case FORM_INPUT_TEXT:
    case FORM_INPUT_FILE:
    case FORM_INPUT_PASSWORD:
    case FORM_TEXTAREA:
#ifdef MENU_SELECT
    case FORM_SELECT:
	if (form->type == FORM_SELECT) {
	    p = form->label->ptr;
	    updateSelectOption(form, form->select_option);
	}
	else
#endif				/* MENU_SELECT */
	{
	    if (!form->value)
		break;
	    p = form->value->ptr;
	}
	l = buf->currentLine;
	if (!l)
	    break;
	if (form->type == FORM_TEXTAREA) {
	    int n = a->y - buf->currentLine->linenumber;
	    if (n > 0)
		for (; l && n; l = l->prev, n--) ;
	    else if (n < 0)
		for (; l && n; l = l->prev, n++) ;
	    if (!l)
		break;
	}
	rows = form->rows ? form->rows : 1;
	col = COLPOS(l, a->start.pos);
	for (c_rows = 0; c_rows < rows; c_rows++, l = l->next) {
	    if (rows > 1) {
		pos = columnPos(l, col);
		a = retrieveAnchor(buf->formitem, l->linenumber, pos);
		if (a == NULL)
		    break;
		spos = a->start.pos;
		epos = a->end.pos;
	    }
	    if (a->start.line != a->end.line || spos > epos || epos >= l->len ||
		spos < 0 || epos < 0 || COLPOS(l, epos) < col)
		break;
	    pos = form_update_line(l, &p, spos, epos, COLPOS(l, epos) - col,
				   rows > 1,
				   form->type == FORM_INPUT_PASSWORD);
	    if (pos != epos) {
		shiftAnchorPosition(buf->href, buf->hmarklist,
				    a->start.line, spos, pos - epos);
		shiftAnchorPosition(buf->name, buf->hmarklist,
				    a->start.line, spos, pos - epos);
		shiftAnchorPosition(buf->img, buf->hmarklist,
				    a->start.line, spos, pos - epos);
		shiftAnchorPosition(buf->formitem, buf->hmarklist,
				    a->start.line, spos, pos - epos);
	    }
	}
	break;
    }
    copyBuffer(buf, &save);
    arrangeLine(buf);
}

formUpdateBuffer(Anchor *a, Buffer *buf, FormItemList *form)
{
    Buffer save;
    char *p;
    int spos, epos, rows, c_rows, pos, col = 0;
    Line *l;

    copyBuffer(&save, buf);
    gotoLine(buf, a->start.line);
    switch (form->type) {
    case FORM_TEXTAREA:
    case FORM_INPUT_TEXT:
    case FORM_INPUT_FILE:
    case FORM_INPUT_PASSWORD:
    case FORM_INPUT_CHECKBOX:
    case FORM_INPUT_RADIO:
#ifdef MENU_SELECT
    case FORM_SELECT:
#endif				/* MENU_SELECT */
	spos = a->start.pos;
	epos = a->end.pos;
	break;
    default:
	spos = a->start.pos + 1;
	epos = a->end.pos - 1;
    }
    switch (form->type) {
    case FORM_INPUT_CHECKBOX:
    case FORM_INPUT_RADIO:
	if (buf->currentLine == NULL ||
	    spos >= buf->currentLine->len || spos < 0)
	    break;
	if (form->checked)
	    buf->currentLine->lineBuf[spos] = '*';
	else
	    buf->currentLine->lineBuf[spos] = ' ';
	break;
    case FORM_INPUT_TEXT:
    case FORM_INPUT_FILE:
    case FORM_INPUT_PASSWORD:
    case FORM_TEXTAREA:
#ifdef MENU_SELECT
    case FORM_SELECT:
	if (form->type == FORM_SELECT) {
	    p = form->label->ptr;
	    updateSelectOption(form, form->select_option);
	}
	else
#endif				/* MENU_SELECT */
	{
	    if (!form->value)
		break;
	    p = form->value->ptr;
	}
	l = buf->currentLine;
	if (!l)
	    break;
	if (form->type == FORM_TEXTAREA) {
	    int n = a->y - buf->currentLine->linenumber;
	    if (n > 0)
		for (; l && n; l = l->prev, n--) ;
	    else if (n < 0)
		for (; l && n; l = l->prev, n++) ;
	    if (!l)
		break;
	}
	rows = form->rows ? form->rows : 1;
	col = COLPOS(l, a->start.pos);
	for (c_rows = 0; c_rows < rows; c_rows++, l = l->next) {
	    if (l == NULL)
		break;
	    if (rows > 1) {
		pos = columnPos(l, col);
		a = retrieveAnchor(buf->formitem, l->linenumber, pos);
		if (a == NULL)
		    break;
		spos = a->start.pos;
		epos = a->end.pos;
	    }
	    if (a->start.line != a->end.line || spos > epos || epos >= l->len ||
		spos < 0 || epos < 0 || COLPOS(l, epos) < col)
		break;
	    pos = form_update_line(l, &p, spos, epos, COLPOS(l, epos) - col,
				   rows > 1,
				   form->type == FORM_INPUT_PASSWORD);
	    if (pos != epos) {
		shiftAnchorPosition(buf->href, buf->hmarklist,
				    a->start.line, spos, pos - epos);
		shiftAnchorPosition(buf->name, buf->hmarklist,
				    a->start.line, spos, pos - epos);
		shiftAnchorPosition(buf->img, buf->hmarklist,
				    a->start.line, spos, pos - epos);
		shiftAnchorPosition(buf->formitem, buf->hmarklist,
				    a->start.line, spos, pos - epos);
	    }
	}
	break;
    }
    copyBuffer(buf, &save);
    arrangeLine(buf);
}


Input:
lexer_process_char_literal (parser_context_t *context_p, /**< context */
                            const uint8_t *char_p, /**< characters */
                            size_t length, /**< length of string */
                            uint8_t literal_type, /**< final literal type */
                            bool has_escape) /**< has escape sequences */
{
  parser_list_iterator_t literal_iterator;
  lexer_literal_t *literal_p;
  uint32_t literal_index = 0;

  JERRY_ASSERT (literal_type == LEXER_IDENT_LITERAL
                || literal_type == LEXER_STRING_LITERAL);

  JERRY_ASSERT (literal_type != LEXER_IDENT_LITERAL || length <= PARSER_MAXIMUM_IDENT_LENGTH);
  JERRY_ASSERT (literal_type != LEXER_STRING_LITERAL || length <= PARSER_MAXIMUM_STRING_LENGTH);

  parser_list_iterator_init (&context_p->literal_pool, &literal_iterator);

  while ((literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
  {
    if (literal_p->type == literal_type
        && literal_p->prop.length == length
        && memcmp (literal_p->u.char_p, char_p, length) == 0)
    {
      context_p->lit_object.literal_p = literal_p;
      context_p->lit_object.index = (uint16_t) literal_index;
      literal_p->status_flags = (uint8_t) (literal_p->status_flags & ~LEXER_FLAG_UNUSED_IDENT);
      return;
    }

    literal_index++;
  }

  JERRY_ASSERT (literal_index == context_p->literal_count);

  if (literal_index >= PARSER_MAXIMUM_NUMBER_OF_LITERALS)
  {
    parser_raise_error (context_p, PARSER_ERR_LITERAL_LIMIT_REACHED);
  }

  literal_p = (lexer_literal_t *) parser_list_append (context_p, &context_p->literal_pool);
  literal_p->prop.length = (uint16_t) length;
  literal_p->type = literal_type;
  literal_p->status_flags = has_escape ? 0 : LEXER_FLAG_SOURCE_PTR;

  if (has_escape)
  {
    literal_p->u.char_p = (uint8_t *) jmem_heap_alloc_block (length);
    memcpy ((uint8_t *) literal_p->u.char_p, char_p, length);
  }
  else
  {
    literal_p->u.char_p = char_p;
  }

  context_p->lit_object.literal_p = literal_p;
  context_p->lit_object.index = (uint16_t) literal_index;
  context_p->literal_count++;
} /* lexer_process_char_literal */

lexer_process_char_literal (parser_context_t *context_p, /**< context */
                            const uint8_t *char_p, /**< characters */
                            size_t length, /**< length of string */
                            uint8_t literal_type, /**< final literal type */
                            bool has_escape) /**< has escape sequences */
{
  parser_list_iterator_t literal_iterator;
  lexer_literal_t *literal_p;
  uint32_t literal_index = 0;

  JERRY_ASSERT (literal_type == LEXER_IDENT_LITERAL
                || literal_type == LEXER_STRING_LITERAL);

  JERRY_ASSERT (literal_type != LEXER_IDENT_LITERAL || length <= PARSER_MAXIMUM_IDENT_LENGTH);
  JERRY_ASSERT (literal_type != LEXER_STRING_LITERAL || length <= PARSER_MAXIMUM_STRING_LENGTH);

  parser_list_iterator_init (&context_p->literal_pool, &literal_iterator);

  while ((literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
  {
    if (literal_p->type == literal_type
        && literal_p->prop.length == length
        && memcmp (literal_p->u.char_p, char_p, length) == 0)
    {
      context_p->lit_object.literal_p = literal_p;
      context_p->lit_object.index = (uint16_t) literal_index;
      literal_p->status_flags = (uint8_t) (literal_p->status_flags & ~LEXER_FLAG_UNUSED_IDENT);
      return;
    }

    literal_index++;
  }

  JERRY_ASSERT (literal_index == context_p->literal_count);

  if (literal_index >= PARSER_MAXIMUM_NUMBER_OF_LITERALS)
  {
    parser_raise_error (context_p, PARSER_ERR_LITERAL_LIMIT_REACHED);
  }

  if (length == 0)
  {
    has_escape = false;
  }

  literal_p = (lexer_literal_t *) parser_list_append (context_p, &context_p->literal_pool);
  literal_p->prop.length = (uint16_t) length;
  literal_p->type = literal_type;
  literal_p->status_flags = has_escape ? 0 : LEXER_FLAG_SOURCE_PTR;

  if (has_escape)
  {
    literal_p->u.char_p = (uint8_t *) jmem_heap_alloc_block (length);
    memcpy ((uint8_t *) literal_p->u.char_p, char_p, length);
  }
  else
  {
    literal_p->u.char_p = char_p;
  }

  context_p->lit_object.literal_p = literal_p;
  context_p->lit_object.index = (uint16_t) literal_index;
  context_p->literal_count++;
} /* lexer_process_char_literal */