diff options
Diffstat (limited to '3rdparty/openpgm-svn-r1135/pgm/packet_parse.c')
-rw-r--r-- | 3rdparty/openpgm-svn-r1135/pgm/packet_parse.c | 619 |
1 files changed, 619 insertions, 0 deletions
diff --git a/3rdparty/openpgm-svn-r1135/pgm/packet_parse.c b/3rdparty/openpgm-svn-r1135/pgm/packet_parse.c new file mode 100644 index 0000000..65c36a9 --- /dev/null +++ b/3rdparty/openpgm-svn-r1135/pgm/packet_parse.c @@ -0,0 +1,619 @@ +/* vim:ts=8:sts=8:sw=4:noai:noexpandtab + * + * PGM packet formats, RFC 3208. + * + * Copyright (c) 2006-2010 Miru Limited. + * + * This library 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; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define __STDC_FORMAT_MACROS +#ifdef _MSC_VER +# include <pgm/wininttypes.h> +#else +# include <inttypes.h> +#endif +#include <impl/i18n.h> +#include <impl/framework.h> +#include <impl/packet_parse.h> + + +//#define PACKET_DEBUG + +#ifndef PACKET_DEBUG +# define PGM_DISABLE_ASSERT +#endif + + +/* locals */ + +static bool pgm_parse (struct pgm_sk_buff_t*const restrict, pgm_error_t**restrict); + + +/* Parse a raw-IP packet for IP and PGM header and any payload. + */ + +#define PGM_MIN_SIZE ( \ + sizeof(struct pgm_ip) + /* IPv4 header */ \ + sizeof(struct pgm_header) /* PGM header */ \ + ) + +bool +pgm_parse_raw ( + struct pgm_sk_buff_t* const restrict skb, /* data will be modified */ + struct sockaddr* const restrict dst, + pgm_error_t** restrict error + ) +{ +/* pre-conditions */ + pgm_assert (NULL != skb); + pgm_assert (NULL != dst); + + pgm_debug ("pgm_parse_raw (skb:%p dst:%p error:%p)", + (const void*)skb, (const void*)dst, (const void*)error); + +/* minimum size should be IPv4 header plus PGM header, check IP version later */ + if (PGM_UNLIKELY(skb->len < PGM_MIN_SIZE)) + { + pgm_set_error (error, + PGM_ERROR_DOMAIN_PACKET, + PGM_ERROR_BOUNDS, + _("IP packet too small at %" PRIu16 " bytes, expecting at least %" PRIu16 " bytes."), + skb->len, (uint16_t)PGM_MIN_SIZE); + return FALSE; + } + +/* IP packet header: IPv4 + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |Version| HL | ToS | Length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Fragment ID |R|D|M| Fragment Offset | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | TTL | Protocol | Checksum | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Source IP Address | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Destination IP Address | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | IP Options when present ... + * +-+-+-+-+-+-+-+-+-+-+-+-+ ... + * | Data ... + * +-+-+- ... + * + * IPv6 + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |Version| Traffic Class | Flow Label | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Payload Length | Next Header | Hop Limit | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | + * | Source IP Address | + * | | + * | | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | + * | Destination IP Address | + * | | + * | | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | IP Options when present ... + * +-+-+-+-+-+-+-+-+-+-+-+-+ ... + * | Data ... + * +-+-+- ... + * + */ + +/* decode IP header */ + const struct pgm_ip* ip = (struct pgm_ip*)skb->data; + switch (ip->ip_v) { + case 4: { + struct sockaddr_in* sin = (struct sockaddr_in*)dst; + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = ip->ip_dst.s_addr; + break; + } + + case 6: + pgm_set_error (error, + PGM_ERROR_DOMAIN_PACKET, + PGM_ERROR_AFNOSUPPORT, + _("IPv6 is not supported for raw IP header parsing.")); + return FALSE; + + default: + pgm_set_error (error, + PGM_ERROR_DOMAIN_PACKET, + PGM_ERROR_AFNOSUPPORT, + _("IP header reports an invalid version %d."), + ip->ip_v); + return FALSE; + } + + const size_t ip_header_length = ip->ip_hl * 4; /* IP header length in 32bit octets */ + if (PGM_UNLIKELY(ip_header_length < sizeof(struct pgm_ip))) + { + pgm_set_error (error, + PGM_ERROR_DOMAIN_PACKET, + PGM_ERROR_BOUNDS, + _("IP header reports an invalid header length %zu bytes."), + ip_header_length); + return FALSE; + } + +#ifndef CONFIG_HOST_ORDER_IP_LEN + size_t packet_length = ntohs (ip->ip_len); /* total packet length */ +#else + size_t packet_length = ip->ip_len; /* total packet length */ +#endif + + +/* ip_len can equal packet_length - ip_header_length in FreeBSD/NetBSD + * Stevens/Fenner/Rudolph, Unix Network Programming Vol.1, p.739 + * + * RFC3828 allows partial packets such that len < packet_length with UDP lite + */ + if (skb->len == packet_length + ip_header_length) { + packet_length += ip_header_length; + } + + if (PGM_UNLIKELY(skb->len < packet_length)) { /* redundant: often handled in kernel */ + pgm_set_error (error, + PGM_ERROR_DOMAIN_PACKET, + PGM_ERROR_BOUNDS, + _("IP packet received at %" PRIu16 " bytes whilst IP header reports %zu bytes."), + skb->len, packet_length); + return FALSE; + } + +/* packets that fail checksum will generally not be passed upstream except with rfc3828 + */ +#ifdef PGM_CHECK_IN_CKSUM + const uint16_t sum = in_cksum (data, packet_length, 0); + if (PGM_UNLIKELY(0 != sum)) { + const uint16_t ip_sum = ntohs (ip->ip_sum); + pgm_set_error (error, + PGM_ERROR_DOMAIN_PACKET, + PGM_ERROR_CKSUM, + _("IP packet checksum mismatch, reported 0x%x whilst calculated 0x%x."), + ip_sum, sum); + return FALSE; + } +#endif + +/* fragmentation offset, bit 0: 0, bit 1: do-not-fragment, bit 2: more-fragments */ +#ifndef CONFIG_HOST_ORDER_IP_OFF + const uint16_t offset = ntohs (ip->ip_off); +#else + const uint16_t offset = ip->ip_off; +#endif + if (PGM_UNLIKELY((offset & 0x1fff) != 0)) { + pgm_set_error (error, + PGM_ERROR_DOMAIN_PACKET, + PGM_ERROR_PROTO, + _("IP header reports packet fragmentation, offset %u."), + offset & 0x1fff); + return FALSE; + } + +/* PGM payload, header looks as follows: + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Source Port | Destination Port | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Type | Options | Checksum | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Global Source ID ... | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | ... Global Source ID | TSDU Length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Type specific data ... + * +-+-+-+-+-+-+-+-+-+- ... + */ + + skb->pgm_header = (void*)( (char*)skb->data + ip_header_length ); + +/* advance DATA pointer to PGM packet */ + skb->data = skb->pgm_header; + skb->len -= ip_header_length; + return pgm_parse (skb, error); +} + +bool +pgm_parse_udp_encap ( + struct pgm_sk_buff_t*const restrict skb, /* will be modified */ + pgm_error_t** restrict error + ) +{ + pgm_assert (NULL != skb); + + if (PGM_UNLIKELY(skb->len < sizeof(struct pgm_header))) { + pgm_set_error (error, + PGM_ERROR_DOMAIN_PACKET, + PGM_ERROR_BOUNDS, + _("UDP payload too small for PGM packet at %" PRIu16 " bytes, expecting at least %zu bytes."), + skb->len, sizeof(struct pgm_header)); + return FALSE; + } + +/* DATA payload is PGM packet, no headers */ + skb->pgm_header = skb->data; + return pgm_parse (skb, error); +} + +/* will modify packet contents to calculate and check PGM checksum + */ +static +bool +pgm_parse ( + struct pgm_sk_buff_t*const restrict skb, /* will be modified to calculate checksum */ + pgm_error_t** restrict error + ) +{ +/* pre-conditions */ + pgm_assert (NULL != skb); + +/* pgm_checksum == 0 means no transmitted checksum */ + if (skb->pgm_header->pgm_checksum) + { + const uint16_t sum = skb->pgm_header->pgm_checksum; + skb->pgm_header->pgm_checksum = 0; + const uint16_t pgm_sum = pgm_csum_fold (pgm_csum_partial ((const char*)skb->pgm_header, skb->len, 0)); + skb->pgm_header->pgm_checksum = sum; + if (PGM_UNLIKELY(pgm_sum != sum)) { + pgm_set_error (error, + PGM_ERROR_DOMAIN_PACKET, + PGM_ERROR_CKSUM, + _("PGM packet checksum mismatch, reported 0x%x whilst calculated 0x%x."), + pgm_sum, sum); + return FALSE; + } + } else { + if (PGM_ODATA == skb->pgm_header->pgm_type || + PGM_RDATA == skb->pgm_header->pgm_type) + { + pgm_set_error (error, + PGM_ERROR_DOMAIN_PACKET, + PGM_ERROR_PROTO, + _("PGM checksum missing whilst mandatory for %cDATA packets."), + PGM_ODATA == skb->pgm_header->pgm_type ? 'O' : 'R'); + return FALSE; + } + pgm_debug ("No PGM checksum :O"); + } + +/* copy packets source transport identifier */ + memcpy (&skb->tsi.gsi, skb->pgm_header->pgm_gsi, sizeof(pgm_gsi_t)); + skb->tsi.sport = skb->pgm_header->pgm_sport; + return TRUE; +} + +/* 8.1. Source Path Messages (SPM) + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | SPM's Sequence Number | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Trailing Edge Sequence Number | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Leading Edge Sequence Number | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | NLA AFI | Reserved | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Path NLA ... | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-...-+-+ + * | Option Extensions when present ... | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- ... -+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * NLA = Network Layer Address + * NLA AFI = NLA Address Family Indicator: rfc 1700 (ADDRESS FAMILY NUMBERS) + * => Path NLA = IP address of last network element + */ + +#define PGM_MIN_SPM_SIZE ( sizeof(struct pgm_spm) ) + +bool +pgm_verify_spm ( + const struct pgm_sk_buff_t*const skb + ) +{ +/* pre-conditions */ + pgm_assert (NULL != skb); + + const struct pgm_spm* spm = (const struct pgm_spm*)skb->data; + switch (ntohs (spm->spm_nla_afi)) { +/* truncated packet */ + case AFI_IP6: + if (PGM_UNLIKELY(skb->len < sizeof(struct pgm_spm6))) + return FALSE; + break; + case AFI_IP: + if (PGM_UNLIKELY(skb->len < sizeof(struct pgm_spm))) + return FALSE; + break; + + default: + return FALSE; + } + + return TRUE; +} + +/* 14.7.1. Poll Request + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | POLL's Sequence Number | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | POLL's Round | POLL's Sub-type | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | NLA AFI | Reserved | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Path NLA ... | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-...-+-+ + * | POLL's Back-off Interval | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Random String | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Matching Bit-Mask | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Option Extensions when present ... | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- ... -+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Sent to ODATA multicast group with IP Router Alert option. + */ + +#define PGM_MIN_POLL_SIZE ( sizeof(struct pgm_poll) ) + +bool +pgm_verify_poll ( + const struct pgm_sk_buff_t*const skb + ) +{ +/* pre-conditions */ + pgm_assert (NULL != skb); + + const struct pgm_poll* poll4 = (const struct pgm_poll*)skb->data; + switch (ntohs (poll4->poll_nla_afi)) { +/* truncated packet */ + case AFI_IP6: + if (PGM_UNLIKELY(skb->len < sizeof(struct pgm_poll6))) + return FALSE; + break; + case AFI_IP: + if (PGM_UNLIKELY(skb->len < sizeof(struct pgm_poll))) + return FALSE; + break; + + default: + return FALSE; + } + + return TRUE; +} + +/* 14.7.2. Poll Response + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | POLR's Sequence Number | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | POLR's Round | reserved | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Option Extensions when present ... | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- ... -+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +bool +pgm_verify_polr ( + const struct pgm_sk_buff_t*const skb + ) +{ +/* pre-conditions */ + pgm_assert (NULL != skb); + +/* truncated packet */ + if (PGM_UNLIKELY(skb->len < sizeof(struct pgm_polr))) + return FALSE; + return TRUE; +} + +/* 8.2. Data Packet + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Data Packet Sequence Number | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Trailing Edge Sequence Number | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Option Extensions when present ... | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- ... -+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Data ... + * +-+-+- ... + */ + +/* no verification api */ + +/* 8.3. NAK + * + * Technically the AFI of the source and multicast group can be different + * but that would be very wibbly wobbly. One example is using a local DLR + * with a IPv4 address to reduce NAK cost for recovery on wide IPv6 + * distribution. + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Requested Sequence Number | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | NLA AFI | Reserved | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Source NLA ... | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-...-+-+ + * | NLA AFI | Reserved | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Multicast Group NLA ... | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-...-+-+ + * | Option Extensions when present ... + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- ... + */ + +#define PGM_MIN_NAK_SIZE ( sizeof(struct pgm_nak) ) + +bool +pgm_verify_nak ( + const struct pgm_sk_buff_t*const skb + ) +{ +/* pre-conditions */ + pgm_assert (NULL != skb); + + pgm_debug ("pgm_verify_nak (skb:%p)", (const void*)skb); + +/* truncated packet */ + if (PGM_UNLIKELY(skb->len < PGM_MIN_NAK_SIZE)) + return FALSE; + + const struct pgm_nak* nak = (struct pgm_nak*)skb->data; + const uint16_t nak_src_nla_afi = ntohs (nak->nak_src_nla_afi); + uint16_t nak_grp_nla_afi = 0; + +/* check source NLA: unicast address of the ODATA sender */ + switch (nak_src_nla_afi) { + case AFI_IP: + nak_grp_nla_afi = ntohs (nak->nak_grp_nla_afi); + break; + + case AFI_IP6: + nak_grp_nla_afi = ntohs (((const struct pgm_nak6*)nak)->nak6_grp_nla_afi); + break; + + default: + return FALSE; + } + +/* check multicast group NLA */ + switch (nak_grp_nla_afi) { + case AFI_IP6: + switch (nak_src_nla_afi) { +/* IPv4 + IPv6 NLA */ + case AFI_IP: + if (PGM_UNLIKELY(skb->len < ( sizeof(struct pgm_nak) + sizeof(struct in6_addr) - sizeof(struct in_addr) ))) + return FALSE; + break; + +/* IPv6 + IPv6 NLA */ + case AFI_IP6: + if (PGM_UNLIKELY(skb->len < sizeof(struct pgm_nak6))) + return FALSE; + break; + } + + case AFI_IP: + break; + + default: + return FALSE; + } + + return TRUE; +} + +/* 8.3. N-NAK + */ + +bool +pgm_verify_nnak ( + const struct pgm_sk_buff_t*const skb + ) +{ +/* pre-conditions */ + pgm_assert (NULL != skb); + + return pgm_verify_nak (skb); +} + +/* 8.3. NCF + */ + +bool +pgm_verify_ncf ( + const struct pgm_sk_buff_t*const skb + ) +{ +/* pre-conditions */ + pgm_assert (NULL != skb); + + return pgm_verify_nak (skb); +} + +/* 13.6. SPM Request + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Option Extensions when present ... + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- ... + */ + +bool +pgm_verify_spmr ( + PGM_GNUC_UNUSED const struct pgm_sk_buff_t*const skb + ) +{ +/* pre-conditions */ + pgm_assert (NULL != skb); + + return TRUE; +} + +/* PGMCC: ACK + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | RX_MAX | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Received Packet Bitmap | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Option Extensions when present ... + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- ... + */ + +#define PGM_MIN_ACK_SIZE ( sizeof(struct pgm_ack) ) + +bool +pgm_verify_ack ( + PGM_GNUC_UNUSED const struct pgm_sk_buff_t*const skb + ) +{ +/* pre-conditions */ + pgm_assert (NULL != skb); + + return TRUE; +} + +/* eof */ |