blob: 5bc8d07ef0e1554647a62a8f02591f2d124194c3 [file] [log] [blame]
Everton Marques871dbcf2009-08-11 15:43:05 -03001/*
2 PIM for Quagga
3 Copyright (C) 2008 Everton da Silva Marques
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; see the file COPYING; if not, write to the
17 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
18 MA 02110-1301 USA
19
20 $QuaggaId: $Format:%an, %ai, %h$ $
21*/
22
23#include "pim_util.h"
24
25/*
26 RFC 3376: 4.1.7. QQIC (Querier's Query Interval Code)
27
28 If QQIC < 128, QQI = QQIC
29 If QQIC >= 128, QQI = (mant | 0x10) << (exp + 3)
30
31 0 1 2 3 4 5 6 7
32 +-+-+-+-+-+-+-+-+
33 |1| exp | mant |
34 +-+-+-+-+-+-+-+-+
35
36 Since exp=0..7 then (exp+3)=3..10, then QQI has
37 one of the following bit patterns:
38
39 exp=0: QQI = 0000.0000.1MMM.M000
40 exp=1: QQI = 0000.0001.MMMM.0000
41 ...
42 exp=6: QQI = 001M.MMM0.0000.0000
43 exp=7: QQI = 01MM.MM00.0000.0000
44 --------- ---------
45 0x4 0x0 0x0 0x0
46*/
47uint8_t igmp_msg_encode16to8(uint16_t value)
48{
49 uint8_t code;
50
51 if (value < 128) {
52 code = value;
53 }
54 else {
55 uint16_t mask = 0x4000;
56 uint8_t exp;
57 uint16_t mant;
58 for (exp = 7; exp > 0; --exp) {
59 if (mask & value)
60 break;
61 mask >>= 1;
62 }
63 mant = 0x000F & (value >> (exp + 3));
64 code = ((uint8_t) 1 << 7) | ((uint8_t) exp << 4) | (uint8_t) mant;
65 }
66
67 return code;
68}
69
70/*
71 RFC 3376: 4.1.7. QQIC (Querier's Query Interval Code)
72
73 If QQIC < 128, QQI = QQIC
74 If QQIC >= 128, QQI = (mant | 0x10) << (exp + 3)
75
76 0 1 2 3 4 5 6 7
77 +-+-+-+-+-+-+-+-+
78 |1| exp | mant |
79 +-+-+-+-+-+-+-+-+
80*/
81uint16_t igmp_msg_decode8to16(uint8_t code)
82{
83 uint16_t value;
84
85 if (code < 128) {
86 value = code;
87 }
88 else {
89 uint16_t mant = (code & 0x0F);
90 uint8_t exp = (code & 0x70) >> 4;
91 value = (mant | 0x10) << (exp + 3);
92 }
93
94 return value;
95}
96
97#ifndef PIM_USE_QUAGGA_INET_CHECKSUM
98/*
99 RFC 3376: 4.1.2. Checksum
100
101 The Checksum is the 16-bit one's complement of the one's complement
102 sum of the whole IGMP message (the entire IP payload). For
103 computing the checksum, the Checksum field is set to zero. When
104 receiving packets, the checksum MUST be verified before processing a
105 packet. [RFC-1071]
106*/
107uint16_t pim_inet_checksum(const char *buf, int size)
108{
109 const uint16_t *ptr;
110 uint32_t sum;
111 uint16_t checksum;
112
113 ptr = (const uint16_t *) buf;
114 sum = 0;
115 while (size > 1) {
116 sum += *ptr;
117 ++ptr;
118 size -= 2;
119 }
120
121 /* Add left-over byte, if any */
122 if (size > 0)
123 sum += (uint16_t) *(const uint8_t *) ptr;
124
125 /* Fold 32-bit sum to 16 bits */
126 sum = (sum & 0xffff) + (sum >> 16);
127
128 checksum = ~sum;
129
130 return checksum;
131}
132#endif /* PIM_USE_QUAGGA_INET_CHECKSUM */