1 /* -*- mode: c; c-file-style: "openbsd" -*- */ 2 /* 3 * Copyright (c) 2009 Vincent Bernat <bernat@luffy.cx> 4 * Copyright (c) 2014 Michael Chapman 5 * 6 * Permission to use, copy, modify, and/or distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #ifndef _FRAME_H 20 #define _FRAME_H 21 22 static union { 23 uint8_t f_uint8; 24 uint16_t f_uint16; 25 uint32_t f_uint32; 26 } types; 27 28 /* This set of macro are used to build packets. The current position in buffer 29 * is `pos'. The length of the remaining space in buffer is `length'. `type' 30 * should be a member of `types'. 31 * 32 * This was stolen from ladvd which was adapted from Net::CDP. The original 33 * author of those macros, Michael Chapman, has relicensed those macros under 34 * the ISC license. */ 35 36 #define POKE(value, type, func) \ 37 ((length >= sizeof(type)) && \ 38 ( \ 39 type = func(value), \ 40 memcpy(pos, &type, sizeof(type)), \ 41 length -= sizeof(type), \ 42 pos += sizeof(type), \ 43 1 \ 44 )) 45 #define POKE_UINT8(value) POKE(value, types.f_uint8, ) 46 #define POKE_UINT16(value) POKE(value, types.f_uint16, htons) 47 #define POKE_UINT32(value) POKE(value, types.f_uint32, htonl) 48 #define POKE_BYTES(value, bytes) \ 49 ((length >= (bytes)) && \ 50 ( \ 51 memcpy(pos, value, bytes), \ 52 length -= (bytes), \ 53 pos += (bytes), \ 54 1 \ 55 )) 56 #define POKE_SAVE(where) \ 57 (where = pos, 1) 58 #define POKE_RESTORE(where) \ 59 do { \ 60 if ((where) > pos) \ 61 length -= ((where) - pos); \ 62 else \ 63 length += (pos - (where)); \ 64 pos = (where); \ 65 } while(0) 66 67 /* This set of macro are used to parse packets. The same variable as for POKE_* 68 * are used. There is no check on boundaries. */ 69 70 #define PEEK(type, func) \ 71 ( \ 72 memcpy(&type, pos, sizeof(type)), \ 73 length -= sizeof(type), \ 74 pos += sizeof(type), \ 75 func(type) \ 76 ) 77 #define PEEK_UINT8 PEEK(types.f_uint8, ) 78 #define PEEK_UINT16 PEEK(types.f_uint16, ntohs) 79 #define PEEK_UINT32 PEEK(types.f_uint32, ntohl) 80 #define PEEK_BYTES(value, bytes) \ 81 do { \ 82 memcpy(value, pos, bytes); \ 83 length -= (bytes); \ 84 pos += (bytes); \ 85 } while (0) 86 #define PEEK_DISCARD(bytes) \ 87 do { \ 88 length -= (bytes); \ 89 pos += (bytes); \ 90 } while (0) 91 #define PEEK_DISCARD_UINT8 PEEK_DISCARD(1) 92 #define PEEK_DISCARD_UINT16 PEEK_DISCARD(2) 93 #define PEEK_DISCARD_UINT32 PEEK_DISCARD(4) 94 #define PEEK_CMP(value, bytes) \ 95 (length -= (bytes), \ 96 pos += (bytes), \ 97 memcmp(pos-bytes, value, bytes)) 98 #define PEEK_SAVE POKE_SAVE 99 #define PEEK_RESTORE POKE_RESTORE 100 101 /* LLDP specific. We need a `tlv' pointer. */ 102 #define POKE_START_LLDP_TLV(type) \ 103 ( \ 104 tlv = pos, \ 105 POKE_UINT16(type << 9) \ 106 ) 107 #define POKE_END_LLDP_TLV \ 108 ( \ 109 memcpy(&types.f_uint16, tlv, sizeof(uint16_t)), \ 110 types.f_uint16 |= htons((pos - (tlv + 2)) & 0x01ff), \ 111 memcpy(tlv, &types.f_uint16, sizeof(uint16_t)), \ 112 1 \ 113 ) 114 115 /* Same for CDP */ 116 #define POKE_START_CDP_TLV(type) \ 117 ( \ 118 (void)POKE_UINT16(type), \ 119 tlv = pos, \ 120 POKE_UINT16(0) \ 121 ) 122 #define POKE_END_CDP_TLV \ 123 ( \ 124 types.f_uint16 = htons(pos - tlv + 2), \ 125 memcpy(tlv, &types.f_uint16, sizeof(uint16_t)), \ 126 1 \ 127 ) 128 129 /* Same for EDP */ 130 #define POKE_START_EDP_TLV(type) \ 131 ( \ 132 (void)POKE_UINT8(EDP_TLV_MARKER), \ 133 (void)POKE_UINT8(type), \ 134 tlv = pos, \ 135 POKE_UINT16(0) \ 136 ) 137 #define POKE_END_EDP_TLV POKE_END_CDP_TLV 138 139 #endif /* _FRAME_H */ 140