module PAP_Types {

/* (C) 2019 by Harald Welte <laforge@gnumonks.org>
 * All rights reserved.
 *
 * Released under the terms of GNU General Public License, Version 2 or
 * (at your option) any later version.
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

import from Osmocom_Types all;

/* RFC1334 */
type enumerated PapCode {
	PAP_AuthenticateReq		('01'O),
	PAP_AuthenticateAck		('02'O),
	PAP_AuthenticateNak		('03'O)
} with { variant "FIELDLENGTH(8)" };

type record PapPacket {
	PapCode		code,
	uint8_t		identifier,
	uint16_t	len,
	PapPayloadUnion	payload
} with {
	variant (len) "LENGTHTO(code,identifier,len,payload)"
	variant (payload) "CROSSTAG( req, code = PAP_AuthenticateReq;
				     ack, code = PAP_AuthenticateAck;
				     nak, code = PAP_AuthenticateNak)"
};

type union PapPayloadUnion {
	PapAuthReq	req,
	PapAuthResp	ack,
	PapAuthResp	nak
};

type record PapAuthReq {
	uint8_t		peer_id_len,
	octetstring	peer_id,
	uint8_t		passwd_len,
	octetstring	passwd
} with {
	variant (peer_id_len) "LENGTHTO(peer_id)"
	variant (passwd_len) "LENGTHTO(passwd)"
};

type record PapAuthResp {
	uint8_t		msg_len,
	charstring	msg
} with { variant (msg_len) "LENGTHTO(msg)" };

external function enc_PapPacket(in PapPacket inp) return octetstring
with { extension "prototype(convert)" extension "encode(RAW)" };

external function dec_PapPacket(in octetstring inp) return PapPacket
with { extension "prototype(convert)" extension "decode(RAW)" };


template (value) PapPacket ts_PAP(template (value) PapCode code, template (value) uint8_t identifier,
				  template (value) PapPayloadUnion payload) := {
	code := code,
	identifier := identifier,
	len := 0, /* overwritten */
	payload := payload
}
template PapPacket tr_PAP(template PapCode code, template uint8_t identifier, template PapPayloadUnion payload) := {
	code := code,
	identifier := identifier,
	len := ?,
	payload := payload
}

template (value) PapPacket ts_PAP_AuthReq(uint8_t identifier := 0, octetstring peer_id, octetstring passwd) :=
	ts_PAP(PAP_AuthenticateReq, identifier,
		{ req := { peer_id_len := 0, peer_id := peer_id,
			   passwd_len := 0, passwd := passwd } });
template PapPacket tr_PAP_AuthReq(template uint8_t identifier := ?, octetstring peer_id, octetstring passwd) :=
	tr_PAP(PAP_AuthenticateReq, identifier,
		{ req := { peer_id_len := ?, peer_id := peer_id,
			   passwd_len := ?, passwd := passwd } });
template (value) PapPacket ts_PAP_AuthAck(uint8_t identifier := 0, charstring msg) :=
	ts_PAP(PAP_AuthenticateAck, identifier, { ack := { msg_len := 0, msg := msg } });
template PapPacket tr_PAP_AuthAck(template uint8_t identifier := ?) :=
	tr_PAP(PAP_AuthenticateAck, identifier, { ack := ? });
template (value) PapPacket ts_PAP_AuthNak(uint8_t identifier := 0, charstring msg) :=
	ts_PAP(PAP_AuthenticateNak, identifier, { nak := { msg_len := 0, msg := msg } });
template PapPacket tr_PAP_AuthNak(template uint8_t identifier := ?) :=
	tr_PAP(PAP_AuthenticateNak, identifier, { nak := ? });

} with { encode "RAW" ; variant "FIELDORDER(msb)" }
