blob: 13230c0ca1e703e04a495be0e37b6e46cd0612d8 [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
Everton Marques62738042009-11-18 10:44:13 -020023#include <zebra.h>
24
25#include "log.h"
26
Everton Marques871dbcf2009-08-11 15:43:05 -030027#include "pim_util.h"
28
29/*
30 RFC 3376: 4.1.7. QQIC (Querier's Query Interval Code)
31
32 If QQIC < 128, QQI = QQIC
33 If QQIC >= 128, QQI = (mant | 0x10) << (exp + 3)
34
35 0 1 2 3 4 5 6 7
36 +-+-+-+-+-+-+-+-+
37 |1| exp | mant |
38 +-+-+-+-+-+-+-+-+
39
40 Since exp=0..7 then (exp+3)=3..10, then QQI has
41 one of the following bit patterns:
42
43 exp=0: QQI = 0000.0000.1MMM.M000
44 exp=1: QQI = 0000.0001.MMMM.0000
45 ...
46 exp=6: QQI = 001M.MMM0.0000.0000
47 exp=7: QQI = 01MM.MM00.0000.0000
48 --------- ---------
49 0x4 0x0 0x0 0x0
50*/
51uint8_t igmp_msg_encode16to8(uint16_t value)
52{
53 uint8_t code;
54
55 if (value < 128) {
56 code = value;
57 }
58 else {
59 uint16_t mask = 0x4000;
60 uint8_t exp;
61 uint16_t mant;
62 for (exp = 7; exp > 0; --exp) {
63 if (mask & value)
64 break;
65 mask >>= 1;
66 }
67 mant = 0x000F & (value >> (exp + 3));
68 code = ((uint8_t) 1 << 7) | ((uint8_t) exp << 4) | (uint8_t) mant;
69 }
70
71 return code;
72}
73
74/*
75 RFC 3376: 4.1.7. QQIC (Querier's Query Interval Code)
76
77 If QQIC < 128, QQI = QQIC
78 If QQIC >= 128, QQI = (mant | 0x10) << (exp + 3)
79
80 0 1 2 3 4 5 6 7
81 +-+-+-+-+-+-+-+-+
82 |1| exp | mant |
83 +-+-+-+-+-+-+-+-+
84*/
85uint16_t igmp_msg_decode8to16(uint8_t code)
86{
87 uint16_t value;
88
89 if (code < 128) {
90 value = code;
91 }
92 else {
93 uint16_t mant = (code & 0x0F);
94 uint8_t exp = (code & 0x70) >> 4;
95 value = (mant | 0x10) << (exp + 3);
96 }
97
98 return value;
99}
100
101#ifndef PIM_USE_QUAGGA_INET_CHECKSUM
102/*
103 RFC 3376: 4.1.2. Checksum
104
105 The Checksum is the 16-bit one's complement of the one's complement
106 sum of the whole IGMP message (the entire IP payload). For
107 computing the checksum, the Checksum field is set to zero. When
108 receiving packets, the checksum MUST be verified before processing a
109 packet. [RFC-1071]
110*/
111uint16_t pim_inet_checksum(const char *buf, int size)
112{
113 const uint16_t *ptr;
114 uint32_t sum;
115 uint16_t checksum;
116
117 ptr = (const uint16_t *) buf;
118 sum = 0;
119 while (size > 1) {
120 sum += *ptr;
121 ++ptr;
122 size -= 2;
123 }
124
125 /* Add left-over byte, if any */
126 if (size > 0)
127 sum += (uint16_t) *(const uint8_t *) ptr;
128
129 /* Fold 32-bit sum to 16 bits */
130 sum = (sum & 0xffff) + (sum >> 16);
131
132 checksum = ~sum;
133
134 return checksum;
135}
136#endif /* PIM_USE_QUAGGA_INET_CHECKSUM */
Everton Marques62738042009-11-18 10:44:13 -0200137
138void pim_pkt_dump(const char *label, const char *buf, int size)
139{
140 char dump_buf[1000];
141 int i = 0;
142 int j = 0;
143
144 for (; i < size; ++i, j += 3) {
145 int left = sizeof(dump_buf) - j;
146 if (left < 4) {
147 if (left > 1) {
148 strcat(dump_buf + j, "!"); /* mark as truncated */
149 }
150 break;
151 }
152 snprintf(dump_buf + j, left, " %02x", buf[i]);
153 }
154
155 zlog_debug("%s: pkt dump size=%d:%s",
156 label,
157 size,
158 dump_buf);
159}