/* * Usurpation – clinet-server protocol implementation. * * Copyright (C) 2019 Ramūnas Mažeikis * Copyright (C) 2019 Gediminas Jakutis * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; version 2.1 * of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ /** * Common parts of protocol implementation. Handling of anything that actually * deals with connection descriptor has to be implemented by device and daemon * separately. */ #include #include #include #include "tlv.h" #include "utils.h" #ifdef unix #include #else #include #endif int tlv_get(char *in, struct tlv *tlv, char **saveptr) { struct tlv_header head; int ret = A_OK; memcpy(&head, in, sizeof(head)); head = ntoh_tlvh(&head); if (head.type == INVALID || !head.size) { ret = NONEWDATA; goto out; } tlv->head = head; tlv->data = in + sizeof(head); if (saveptr) { *saveptr = in + sizeof(head) + head.size; } out: return ret; } struct tlv_header ntoh_tlvh(const struct tlv_header * const in) { struct tlv_header ret; ret.type = ntohl(in->type); ret.size = ntohl(in->size); return ret; } struct tlv_header hton_tlvh(const struct tlv_header * const in) { struct tlv_header ret; ret.type = htonl(in->type); ret.size = htonl(in->size); return ret; } int tlv_pack(struct tlv_packet *pack, struct tlv *tlv) { struct tlv_header head; size_t raw_size; int ret = A_OK; /* packed tlv loses the pointer, so only take the header part into account */ raw_size = sizeof(tlv->head) + tlv->head.size; if ((raw_size + pack->cursor + sizeof(tlv->head)) >= TLV_SZ_MAX) { ret = ERROR; } else { if (pack->size < pack->cursor + raw_size) { pack->data = realloc(pack->data, pack->size + raw_size); pack->size += raw_size; } head = tlv->head; head = hton_tlvh(&head); memcpy(pack->data + pack->cursor, &head, sizeof(head)); pack->cursor += sizeof(tlv->head); if (tlv->head.size && tlv->data) { memcpy(pack->data + pack->cursor, tlv->data, tlv->head.size); pack->cursor += tlv->head.size; } } return ret; } int tlv_packet_finalize(struct tlv_packet *pack) { struct tlv terminator; int ret = A_OK; terminator = tlv_none; tlv_pack(pack, &terminator); return ret; } struct tlv *tlv_init(struct tlv *in, enum tlv_type type) { in->head.type = type; in->head.size = 0; in->data = NULL; return in; } void tlv_destroy(struct tlv *in) { free(in->data); *in = tlv_none; } struct tlv_packet *tlv_packet_init(struct tlv_packet *in) { in->size = 0; in->cursor = 0; in->data = NULL; return in; } struct tlv_packet *tlv_packet_reset(struct tlv_packet *in) { memset(in->data, 0, in->cursor); in->cursor = 0; return in; } void tlv_packet_destroy(struct tlv_packet *in) { free(in->data); in->size = 0; in->cursor = 0; in->data = NULL; }