trafgen: add smoke test for drnd packets
[netsniff-ng.git] / src / mops_ext_igmp.c
blob3bd83fa05bf5a7f2350032632a6b85f3ef533e0a
1 /*
2 * Mausezahn - A fast versatile traffic generator
3 * Copyright (C) 2008-2010 Herbert Haas
4 *
5 * This program is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU General Public License version 2 as published by the
7 * Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12 * details.
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, see http://www.gnu.org/licenses/gpl-2.0.html
19 #include "mz.h"
20 #include "mops.h"
21 #include "cli.h"
25 // Initialization function - specify defaults here!
26 //
27 int mops_init_pdesc_igmp(struct mops *mp)
29 struct mops_ext_igmp * pd;
31 if (mp->p_desc == NULL) return 1; // p_desc not properly assigned
32 pd = mp->p_desc;
34 pd->version = 2;
35 pd->type = IGMP_V2_REPORT;
36 pd->max_resp_code = 0;
37 pd->sum_false = 0;
38 pd->group_addr = 0; // TODO: consider initialization with well-known mcast address?
39 pd->sa_list = NULL;
41 return 0;
47 // IGMPv2 query and report (see RFC 2236)
49 // 0 1 2 3
50 // 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
51 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
52 // | Type | Max Resp Time | Checksum |
53 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
54 // | Group Address |
55 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
56 //
57 //
58 // IGMPv1 query and report (see RFC 1112)
60 // 0 1 2 3
61 // 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
62 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
63 // |Version| Type | Unused | Checksum |
64 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
65 // | Group Address |
66 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
68 // Therefore IGMPv1 only uses IGMP_GENERAL_QUERY or IGMP_V1_REPORT and mrt=0.
70 int mops_create_igmpv2 (struct mops *mp,
71 int override, // normally zero, but if '1' the user want to override defaults
72 int igmp_type, // IGMP_GENERAL_QUERY, IGMP_GSPEC_QUERY, IGMP_V2_REPORT, IGMP_V1_REPORT, IGMP_LEAVE
73 int mrt, // max response time (unused == 0 for IGMPv1)
74 int sum, //-1 means auto-compute, other values means 'use this user-defined value'
75 u_int32_t group_addr)
77 struct mops_ext_igmp * pd;
79 // --- sanity check params ---
80 // Do we have a valid pointer?
81 if (mp->p_desc == NULL) return 1; // p_desc not properly assigned
82 pd = mp->p_desc;
83 if (mrt>255) return 1;
84 if (sum>65535) return 1;
85 // ---------------------------
87 // +++ Set values in pdesc ++++++++++++++++++++++++
88 pd->version = 2;
90 switch (igmp_type) {
91 case IGMP_GENERAL_QUERY:
92 pd->type = 0x11;
93 pd->group_addr = 0;
94 pd->max_resp_code = mrt;
95 break;
96 case IGMP_GSPEC_QUERY:
97 pd->type = 0x11;
98 pd->group_addr = group_addr;
99 pd->max_resp_code = mrt;
100 break;
101 case IGMP_V2_REPORT:
102 pd->type = 0x16;
103 pd->group_addr = group_addr;
104 if (override) pd->max_resp_code = mrt; else pd->max_resp_code = 0;
105 break;
106 case IGMP_V1_REPORT:
107 pd->type = 0x12;
108 pd->group_addr = group_addr;
109 if (override) pd->max_resp_code = mrt; else pd->max_resp_code = 0;
110 break;
111 case IGMP_LEAVE:
112 pd->type = 0x17;
113 pd->group_addr = group_addr;
114 if (override) pd->max_resp_code = mrt; else pd->max_resp_code = 0;
115 break;
116 default:
117 return 1; // unknown type
120 if (sum==-1) {
121 pd->sum_false = 0;
122 } else {
123 pd->sum_false = 1;
124 pd->sum = sum; // mops_update_igmp() will process this!
127 // ++++++++++++++++++++++++++++++++++++++++++++++++
129 return 0;
140 int mops_update_igmp (struct mops * mp)
142 struct mops_ext_igmp * pd;
144 pd = mp->p_desc;
145 if (pd==NULL) return 1; // no valid pointer to a p_desc
146 mp->msg_s = 0; // important! Otherwise the msg would get longer and longer after each call!
147 u_int16_t sum;
149 switch (pd->version) {
151 case 1:
152 break;
154 case 2:
155 // IGMPv2 query and report (see RFC 2236)
157 // 0 1 2 3
158 // 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
159 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
160 // | Type | Max Resp Time | Checksum |
161 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
162 // | Group Address |
163 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
165 mops_msg_add_byte (mp, pd->type);
166 mops_msg_add_byte (mp, pd->max_resp_code);
167 if (pd->sum_false)
168 mops_msg_add_2bytes (mp, pd->sum); // used defined (typically wrong) checksum
169 else // must be set to zero before checksum computation
170 mops_msg_add_2bytes (mp, 0x0000);
171 mops_msg_add_4bytes (mp, pd->group_addr);
172 if (pd->sum_false==0) {
173 sum = mops_sum16 (mp->msg_s, mp->msg);
174 mops_hton2(&sum, &mp->msg[2]);
176 break;
178 case 3:
179 break;
182 default:
183 return 1;
188 return 0;
198 // IGMP messages are encapsulated in IPv4 datagrams, with an IP protocol
199 // number of 2. Every IGMP message described in this document is sent
200 // with an IP Time-to-Live of 1, IP Precedence of Internetwork Control
201 // (e.g., Type of Service 0xc0), and carries an IP Router Alert option
202 // [RFC-2113] in its IP header.
208 // IGMPv3 report message (see RFC 3376)
210 // 0 1 2 3
211 // 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
212 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
213 // | Type = 0x22 | Reserved | Checksum |
214 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
215 // | Reserved | Number of Group Records (M) |
216 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
217 // | |
218 // . .
219 // . Group Record [1] .
220 // . .
221 // | |
222 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
223 // | |
224 // . .
225 // . Group Record [2] .
226 // . .
227 // | |
228 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
229 // | . |
230 // . . .
231 // | . |
232 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
233 // | |
234 // . .
235 // . Group Record [M] .
236 // . .
237 // | |
238 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
243 // IGMPv3 query message (see RFC 3376)
245 // 0 1 2 3
246 // 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
247 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
248 // | Type = 0x11 | Max Resp Code | Checksum |
249 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
250 // | Group Address |
251 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
252 // | Resv |S| QRV | QQIC | Number of Sources (N) |
253 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
254 // | Source Address [1] |
255 // +- -+
256 // | Source Address [2] |
257 // +- . -+
258 // . . .
259 // . . .
260 // +- -+
261 // | Source Address [N] |
262 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+