2 * Mausezahn - A fast versatile traffic generator
3 * Copyright (C) 2008-2010 Herbert Haas
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.
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
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
23 // int mops_update (stuct mops *mp)
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
36 int mops_update (struct mops
*mp
)
39 i
, // the standard loop variable; outside a loop fully undetermined!
41 fp
=0; // frame pointer; always points to NEXT byte
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];
55 mp
->frame
[i
] = mp
->eth_dst
[i
];
56 mp
->frame
[i
+6] = mp
->eth_src
[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!
79 x
= (char*) &mp
->eth_len
;
80 mp
->frame
[fp
++] = *(x
+1);
86 mp
->frame
[fp
++] = mp
->eth_snap
[i
];
89 else if (mp
->use_ETHER
) // add TYPE field (note the ELSE IF here!)
92 x
= (char*) &mp
->eth_type
;
93 mp
->frame
[fp
++] = *(x
+1);
96 // alternatively the user specified whole raw frame
106 mp
->frame
[fp
++] = mp
->mpls
[i
];
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)
126 // ----- 2nd row: -----
128 mops_hton2 ( &mp
->ip_id
, &mp
->frame
[fp
] ); // Fragment Identification
131 mops_hton2 ( &mp
->ip_frag_offset
, &mp
->frame
[fp
] ); // Fragment Identification
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
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)
145 // ----- 4th and 5th row: -----
147 mops_hton4 ( &mp
->ip_src
, &mp
->frame
[fp
] ); // SA
149 mops_hton4 ( &mp
->ip_dst
, &mp
->frame
[fp
] ); // DA
152 // ----- options -----
154 if (mp
->ip_option_used
)
159 mp
->frame
[fp
++] = mp
->ip_option
[i
];
170 mp
->begin_UDP
= fp
; // marks byte position of UDP header within frame
172 mops_hton2 ( &mp
->sp
, &mp
->frame
[fp
] ); // Source Port
174 mops_hton2 ( &mp
->dp
, &mp
->frame
[fp
] ); // Destination Port
176 mops_hton2 ( &mp
->udp_len
, &mp
->frame
[fp
] ); // Length (user value - corrected at end of function if required)
178 mops_hton2 ( &mp
->udp_sum
, &mp
->frame
[fp
] ); // CheckSum (user value - corrected at end of function if required)
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
193 mops_hton2 ( &mp
->dp
, &mp
->frame
[fp
] ); // Destination Port
196 // ----- 2nd and 3rd row: -----
198 mops_hton4 ( &mp
->tcp_seq
, &mp
->frame
[fp
] ); // SQNR
200 mops_hton4 ( &mp
->tcp_ack
, &mp
->frame
[fp
] ); // ACKNR
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
222 mops_hton2 ( &mp
->tcp_win
, &mp
->frame
[fp
] ); // Window
225 // ----- 5th row: -----
227 mops_hton2 ( &mp
->tcp_sum
, &mp
->frame
[fp
] ); // Checksum
230 mops_hton2 ( &mp
->tcp_urg
, &mp
->frame
[fp
] ); // Urgent pointer
234 // ----- options: -----
236 if (mp
->tcp_option_used
) {
238 for (i
=0; i
<t
; i
++) {
239 mp
->frame
[fp
++] = mp
->tcp_option
[i
];
244 // Eventually the payload:
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
;
263 if (fp
> max_frame_s
)
264 mp
->frame_s
= max_frame_s
;
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
282 fp
= mp
->begin_IP
; // marks byte position of IP header within frame
285 if (!mp
->ip_IHL_false
) { // user has NOT set an own header length
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
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
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)
312 fp
= mp
->begin_UDP
; // marks byte position of UDP header within frame
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
322 // The pseudo header conceptually prefixed to the UDP header contains the
323 // source address, the destination address, the protocol, and the UDP
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)
355 mp
->frame
[mp
->frame_s
]=0x00;
356 memcpy(&mp
->frame
[mp
->frame_s
+1], ip_pseudo_header
, 12);
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] );
371 fp
= mp
->begin_TCP
; // marks byte position of TCP header within frame
374 if (!mp
->tcp_offset_false
) // user has NOT set an own header length
377 if (mp
->tcp_option_used
) {// add option length if option exists
378 t8
+= mp
->tcp_option_s
/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)
407 mp
->frame
[mp
->frame_s
]=0x00;
408 memcpy(&mp
->frame
[mp
->frame_s
+1], ip_pseudo_header
, 12);
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] );