trafgen: print seed on smoke-test, set seed manually
[netsniff-ng.git] / src / mops_update.c
blob4fa1b3a3aef08280523401985e5161e837ef8d13
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
22 // -- TOC: --
23 // int mops_update (stuct mops *mp)
26 #include "mz.h"
27 #include "mops.h"
31 // This is the very basic MOPS update function. It simply updates the whole
32 // MOPS frame specified by the pointer mp. If you only want to update specific
33 // details then please see the other related specialized functions which are
34 // more effcient.
36 int mops_update (struct mops *mp)
38 int
39 i, // the standard loop variable; outside a loop fully undetermined!
40 t, // temp
41 fp=0; // frame pointer; always points to NEXT byte
43 char *x;
44 u_int8_t t8=0; // temp 8 bits
45 u_int16_t t16; // temp 16 bits
47 u_int8_t ip_pseudo_header[12];
50 // set MAC addresses?
51 if (mp->use_ETHER)
53 for (i=0; i<6; i++)
55 mp->frame[i] = mp->eth_dst[i];
56 mp->frame[i+6] = mp->eth_src[i];
58 fp = 12; // next byte
63 // VLAN tags?
64 if (mp->use_dot1Q)
66 t = mp->dot1Q_s;
67 for (i=0; i<t; i++)
69 mp->frame[fp++] = mp->dot1Q[i];
75 // Standard Ethernet or SNAP? (SNAP includes 802.3, see comments in mops.h)
76 if (mp->use_SNAP) // note that if use_SNAP is set, then the 'else if' below is ignored!
78 // 802.3 length
79 x = (char*) &mp->eth_len;
80 mp->frame[fp++] = *(x+1);
81 mp->frame[fp++] = *x;
82 // SNAP
83 t = mp->eth_snap_s;
84 for (i=0; i<t; i++)
86 mp->frame[fp++] = mp->eth_snap[i];
89 else if (mp->use_ETHER) // add TYPE field (note the ELSE IF here!)
91 // EtherType
92 x = (char*) &mp->eth_type;
93 mp->frame[fp++] = *(x+1);
94 mp->frame[fp++] = *x;
96 // alternatively the user specified whole raw frame
97 //
98 //
99 //
100 // MPLS?
101 if (mp->use_MPLS)
103 t = mp->mpls_s;
104 for (i=0; i<t; i++)
106 mp->frame[fp++] = mp->mpls[i];
113 // IP?
114 if (mp->use_IP)
116 mp->begin_IP = fp; // marks byte position of IP header within frame
118 // ----- 1st row: -----
120 mp->frame[fp] = (mp->ip_version << 4); // version
121 mp->frame[fp++] |= mp->ip_IHL; // IHL (user value - corrected at end of function if required)
122 mp->frame[fp++] = mp->ip_tos; // ToS
123 mops_hton2 ( &mp->ip_len, &mp->frame[fp] ); // Total Length (user value - corrected at end of function if required)
124 fp+=2;
126 // ----- 2nd row: -----
128 mops_hton2 ( &mp->ip_id, &mp->frame[fp] ); // Fragment Identification
129 fp+=2;
131 mops_hton2 ( &mp->ip_frag_offset, &mp->frame[fp] ); // Fragment Identification
132 // set flags:
133 if (mp->ip_flags_MF) mp->frame[fp] |= 0x20; else mp->frame[fp] &= 0xDF; // More Frag
134 if (mp->ip_flags_DF) mp->frame[fp] |= 0x40; else mp->frame[fp] &= 0xBF; // Don't Frag
135 if (mp->ip_flags_RS) mp->frame[fp] |= 0x80; else mp->frame[fp] &= 0x7F; // reserved
136 fp+=2;
138 // ----- 3rd row: -----
140 mp->frame[fp++] = mp->ip_ttl; // TTL
141 mp->frame[fp++] = mp->ip_proto; // Protocol
142 mops_hton2 ( &mp->ip_sum, &mp->frame[fp] ); // Checksum (user value - corrected at end of function if required)
143 fp+=2;
145 // ----- 4th and 5th row: -----
147 mops_hton4 ( &mp->ip_src, &mp->frame[fp] ); // SA
148 fp+=4;
149 mops_hton4 ( &mp->ip_dst, &mp->frame[fp] ); // DA
150 fp+=4;
152 // ----- options -----
154 if (mp->ip_option_used)
156 t = mp->ip_option_s;
157 for (i=0; i<t; i++)
159 mp->frame[fp++] = mp->ip_option[i];
167 // UDP?
168 if (mp->use_UDP)
170 mp->begin_UDP = fp; // marks byte position of UDP header within frame
172 mops_hton2 ( &mp->sp, &mp->frame[fp] ); // Source Port
173 fp+=2;
174 mops_hton2 ( &mp->dp, &mp->frame[fp] ); // Destination Port
175 fp+=2;
176 mops_hton2 ( &mp->udp_len, &mp->frame[fp] ); // Length (user value - corrected at end of function if required)
177 fp+=2;
178 mops_hton2 ( &mp->udp_sum, &mp->frame[fp] ); // CheckSum (user value - corrected at end of function if required)
179 fp+=2;
184 // TCP?
185 if (mp->use_TCP)
187 mp->begin_TCP = fp; // marks byte position of TCP header within frame
189 // ----- 1st row: -----
191 mops_hton2 ( &mp->sp, &mp->frame[fp] ); // Source Port
192 fp+=2;
193 mops_hton2 ( &mp->dp, &mp->frame[fp] ); // Destination Port
194 fp+=2;
196 // ----- 2nd and 3rd row: -----
198 mops_hton4 ( &mp->tcp_seq, &mp->frame[fp] ); // SQNR
199 fp+=4;
200 mops_hton4 ( &mp->tcp_ack, &mp->frame[fp] ); // ACKNR
201 fp+=4;
203 // ----- 4th row: -----
205 // t16 = (mp->tcp_offset<<12) + (mp->tcp_res<<8); // Data Offset (HLEN) and 4 reserved bits
206 t16 = mp->tcp_res<<8; // Data Offset (HLEN) and 4 reserved bits
207 // (user value - corrected at end of function if required)
209 if (mp->tcp_ctrl_CWR) t16 |= 0x0080; else t16 &= 0xff7f; // URG Flag
210 if (mp->tcp_ctrl_ECE) t16 |= 0x0040; else t16 &= 0xffbf; // URG Flag
211 if (mp->tcp_ctrl_URG) t16 |= 0x0020; else t16 &= 0xffdf; // URG Flag
212 if (mp->tcp_ctrl_ACK) t16 |= 0x0010; else t16 &= 0xffef; // ACK Flag
213 if (mp->tcp_ctrl_PSH) t16 |= 0x0008; else t16 &= 0xfff7; // PSH Flag
214 if (mp->tcp_ctrl_RST) t16 |= 0x0004; else t16 &= 0xfffb; // RST Flag
215 if (mp->tcp_ctrl_SYN) t16 |= 0x0002; else t16 &= 0xfffd; // SYN Flag
216 if (mp->tcp_ctrl_FIN) t16 |= 0x0001; else t16 &= 0xfffe; // FIN Flag
218 mops_hton2 ( &t16, &mp->frame[fp] ); // copy HLEN, reserved bits, and flags to frame
219 fp+=2;
222 mops_hton2 ( &mp->tcp_win, &mp->frame[fp] ); // Window
223 fp+=2;
225 // ----- 5th row: -----
227 mops_hton2 ( &mp->tcp_sum, &mp->frame[fp] ); // Checksum
228 fp+=2;
230 mops_hton2 ( &mp->tcp_urg, &mp->frame[fp] ); // Urgent pointer
231 fp+=2;
234 // ----- options: -----
236 if (mp->tcp_option_used) {
237 t=mp->tcp_option_s;
238 for (i=0; i<t; i++) {
239 mp->frame[fp++] = mp->tcp_option[i];
244 // Eventually the payload:
245 if ((t = mp->msg_s))
247 mp->begin_MSG = fp;
248 for (i=0; i<t; i++) {
249 mp->frame[fp++] = mp->msg[i];
253 mp->frame_s = fp; // finally set the total frame length
256 //////////////////////////////////////////////////////////////
257 // Protect TX subsystem from too short or long packets //
258 // TODO: Consider to support mops-specific limits
259 // (which are itself limited by these global limits)
260 if (fp < min_frame_s)
261 mp->frame_s = min_frame_s;
262 else
263 if (fp > max_frame_s)
264 mp->frame_s = max_frame_s;
265 // //
266 //////////////////////////////////////////////////////////////
271 ////////////////////////////////////////////////////////////////////////////////
273 // Now update "derivable" fields if required:
275 // IP: ip_IHL, ip_len, ip_sum
276 // UDP: udp_len, udp_sum
277 // TCP: tcp_offset, tcp_sum
280 if (mp->use_IP)
282 fp = mp->begin_IP; // marks byte position of IP header within frame
284 /// HLEN
285 if (!mp->ip_IHL_false) { // user has NOT set an own header length
286 t8 = 5;
287 if (mp->ip_option_used) { // add option length if option exists
288 t8 += mp->ip_option_s/4;
290 t8 &= 0x0f; // set most significant 4 bits to zero because reserved for IP version
291 mp->frame[fp] |= t8;
294 /// LEN
295 if (!mp->ip_len_false) { // user has NOT set an own total length
296 t16 = mp->frame_s-fp;
297 mops_hton2 ( &t16, &mp->frame[fp+2] ); // Calculated total Length
300 /// SUM
301 if (!mp->ip_sum_false) { // user has NOT set an own header checksum
302 mp->frame[fp+10]=0x00;
303 mp->frame[fp+11]=0x00;
304 t16 = mops_sum16 (t8*4, &mp->frame[fp]);
305 mops_hton2 ( &t16, &mp->frame[fp+10] ); // Checksum (user value - corrected at end of function if required)
310 if (mp->use_UDP)
312 fp = mp->begin_UDP; // marks byte position of UDP header within frame
314 /// LEN
315 if (!mp->udp_len_false) { // user has NOT set an own total length
316 t16 = mp->frame_s-fp;
317 mops_hton2 ( &t16, &mp->frame[fp+4] ); // Calculated total Length
320 /// SUM
322 // The pseudo header conceptually prefixed to the UDP header contains the
323 // source address, the destination address, the protocol, and the UDP
324 // length. [RFC 768]
326 // 0 7 8 15 16 23 24 31
327 // +--------+--------+--------+--------+
328 // | source address |
329 // +--------+--------+--------+--------+
330 // | destination address |
331 // +--------+--------+--------+--------+
332 // | zero |protocol| UDP length |
333 // +--------+--------+--------+--------+
336 if (!mp->udp_sum_false) // user has NOT set an own checksum
338 // Create IP pseudoheader
339 memcpy(&ip_pseudo_header[0], &mp->frame[mp->begin_IP+12], 4); // copy SA to pseudoheader
340 memcpy(&ip_pseudo_header[4], &mp->frame[mp->begin_IP+16], 4); // copy DA to pseudoheader
341 ip_pseudo_header[8]=0x00;
342 ip_pseudo_header[9]=mp->ip_proto;
343 memcpy(&ip_pseudo_header[10], &mp->frame[fp+4], 2); // copy UDP length to pseudoheader
345 mp->frame[fp+6]=0x00; // set checksum to 0x0000
346 mp->frame[fp+7]=0x00;
348 t = 12+mp->frame_s-fp; // udp datagram length (including 12 byte pseudoheader)
350 // Pad one extra byte if length is odd, and append the
351 // pseudoheader at the end of mp->frame (only for checksum computation)
352 if (t%2)
354 t++;
355 mp->frame[mp->frame_s]=0x00;
356 memcpy(&mp->frame[mp->frame_s+1], ip_pseudo_header, 12);
358 else
359 memcpy(&mp->frame[mp->frame_s], ip_pseudo_header, 12);
361 t16 = mops_sum16 (t, &mp->frame[fp]);
362 mops_hton2 ( &t16, &mp->frame[fp+6] );
369 if (mp->use_TCP)
371 fp = mp->begin_TCP; // marks byte position of TCP header within frame
373 /// OFFSET (=HLEN)
374 if (!mp->tcp_offset_false) // user has NOT set an own header length
376 t8 = 5;
377 if (mp->tcp_option_used) {// add option length if option exists
378 t8 += mp->tcp_option_s/4;
380 t8 <<=4;
381 mp->frame[fp+12] |= t8;
384 // The TCP checksum is calculated similarily as the UDP checksum (see above).
385 // (The TCP length is needed instead of the UDP length of course, although
386 // the TCP length is not part of the header)
388 if (!mp->tcp_sum_false) {
389 // Create IP pseudoheader
390 memcpy(&ip_pseudo_header[0], &mp->frame[mp->begin_IP+12], 4); // copy SA to pseudoheader
391 memcpy(&ip_pseudo_header[4], &mp->frame[mp->begin_IP+16], 4); // copy DA to pseudoheader
392 ip_pseudo_header[8]=0x00;
393 ip_pseudo_header[9]=mp->ip_proto;
394 mp->tcp_len = mp->frame_s-fp; // TCP segment length
395 t16 = htons (mp->tcp_len);
396 memcpy(&ip_pseudo_header[10], &t16, 2); // copy TCP length to pseudoheader
398 mp->frame[fp+16]=0x00; // set checksum to 0x0000
399 mp->frame[fp+17]=0x00;
401 t = mp->tcp_len+12; // TCP segment length plus pseudoheader length
403 // Pad one extra byte if length is odd, and append the
404 // pseudoheader at the end of mp->frame (only for checksum computation)
405 if (t%2) {
406 t++;
407 mp->frame[mp->frame_s]=0x00;
408 memcpy(&mp->frame[mp->frame_s+1], ip_pseudo_header, 12);
410 else
411 memcpy(&mp->frame[mp->frame_s], ip_pseudo_header, 12);
413 t16 = mops_sum16 (t, &mp->frame[fp]);
414 mops_hton2 ( &t16, &mp->frame[fp+16] );
419 return 0;