flowtop: make function nested
[netsniff-ng.git] / src / mops_ext_bpdu.c
blob8cb180d55e985e527fb7e2f88e2943353c4de9ae
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
21 #include "mz.h"
22 #include "mops.h"
25 // Initialization function - specify defaults here!
26 //
27 int mops_init_pdesc_bpdu(struct mops *mp)
29 struct mops_ext_bpdu * pd;
30 int i;
33 if (mp->p_desc == NULL) return 1; // p_desc not properly assigned
34 pd = mp->p_desc;
36 // 1. - Initialize Ethernet header
37 str2hex("01:80:C2:00:00:00",mp->eth_dst, 6);
39 // 2. - Initialize BPDU fields
40 pd->id = 0;
41 pd->version = 0; // 0=802.1D, 2=RSTP(802.1w)
42 pd->bpdu_type = 0x80; // 0=conf, 0x80=topology change, 2=RSTP/MSTP
43 pd->flags = 0; // X... .... = TCN ACK
44 // .X.. .... = Agreement
45 // ..X. .... = Forwarding
46 // ...X .... = Learning
47 // .... XX.. = Port Role (e. g. 11=Desgn)
48 // .... ..X. = Proposal
49 // .... ...X = TCN
51 i = mops_get_device_index(tx.device);
52 if (i!=-1) { // found
53 memcpy((void*) &pd->root_id[2], (void*) device_list[i].mac_mops, 6);
54 memcpy((void*) &pd->bridge_id[2], (void*) device_list[i].mac_mops, 6);
55 } else {
56 str2hex("00:00:00:00:00:00", &pd->root_id[2], 6);
57 str2hex("00:00:00:00:00:00", &pd->bridge_id[2], 6);
60 pd->root_id[0] = 0x00;
61 pd->root_id[1] = 0x00;
63 pd->bridge_id[0] = 0x00;
64 pd->bridge_id[1] = 0x00;
66 pd->root_pc = 0; // Root Path Cost
67 pd->port_id = 0; // Port Identifier
68 pd->message_age = 0; // All timers are multiples of 1/256 sec. Thus times range from 0 to 256 seconds.
69 pd->max_age = 5120; // 20 seconds
70 pd->hello_time = 512;
71 pd->f_delay = 3840;
73 str2hex("00:00:00:00:00:00:00:00", pd->trailer, 8);
74 // either all-zero or 00:00:00:00:02:VLAN(16bit) when PVST+
75 pd->rstp = 0; // 1 = RSTP
76 pd->pvst = 0; // 1=PVST+ , 0 = 802.1D
77 pd->mstp = 0; // 1 = Multiple Instance STP
79 return 0;
83 /////////////////////////////////////////////////////////////////////////////////
84 /////////////////////////////// Update functions ////////////////////////////////
86 // **** Here is a summary of mops tool functions: ****
88 // Adds single byte to msg
89 // int mops_msg_add_byte (struct mops *mp, u_int8_t data);
90 //
91 // Adds bit field in *previous* msg-byte using optional left-shift
92 // int mops_msg_add_field (struct mops *mp, u_int8_t data, int shift);
93 //
94 // Adds two bytes in network byte order to msg
95 // int mops_msg_add_2bytes (struct mops *mp, u_int16_t data);
96 //
97 // Adds four bytes in network byte order to msg
98 // int mops_msg_add_4bytes (struct mops *mp, u_int32_t data);
99 //
100 // Adds string of bytes with lenght len
101 // int mops_msg_add_string (struct mops *mp, u_int8_t *str, int len);
103 int mops_update_bpdu(struct mops * mp)
106 struct mops_ext_bpdu * pd;
108 pd = mp->p_desc;
109 if (pd==NULL) return 1; // no valid pointer to a p_desc
110 mp->msg_s = 0; // important! Otherwise the msg would get longer and longer after each call!
113 // NOTE: the length field does not include the trailer!
114 if (pd->pvst)
116 str2hex("01:00:0C:CC:CC:CD", mp->eth_dst, 6);
117 mp->eth_len=50;
118 str2hex("aa:aa:03:00:00:0c:01:0b",mp->eth_snap, 8);
119 mp->eth_snap_s = 8;
121 else
123 str2hex("01:80:C2:00:00:00",mp->eth_dst, 6);
124 mp->eth_len=38;
125 str2hex("42:42:03",mp->eth_snap, 3);
126 mp->eth_snap_s = 3;
129 mops_msg_add_2bytes (mp, pd->id);
130 mops_msg_add_byte (mp, pd->version);
131 mops_msg_add_byte (mp, pd->bpdu_type);
133 if (pd->bpdu_type & 0x80) // if TCN then don't add more fields
135 if (pd->pvst) mp->eth_len=12; else mp->eth_len=7;
137 else
139 mops_msg_add_byte (mp, pd->flags);
140 mops_msg_add_string (mp, pd->root_id, 8);
141 mops_msg_add_4bytes (mp, pd->root_pc);
142 mops_msg_add_string (mp, pd->bridge_id, 8);
143 mops_msg_add_2bytes (mp, pd->port_id);
144 mops_msg_add_2bytes (mp, pd->message_age);
145 mops_msg_add_2bytes (mp, pd->max_age);
146 mops_msg_add_2bytes (mp, pd->hello_time);
147 mops_msg_add_2bytes (mp, pd->f_delay);
150 // we always add the trailer
151 mops_msg_add_string (mp, pd->trailer, 8);
153 return 0;
158 // Create RID or BID based on priority, ext-sys-id, and MAC address.
159 // The last parameter selects BID (0) or RID (1)
161 // pri .... 0-15
162 // esi .... 0-4095
163 // mac .... XX:XX:XX:XX:XX:XX or interface name
165 // NOTE: Invalid parameters will result in default values
167 // RETURN VALUE: Only informational; identifies which parameter
168 // was errourness, using the following values:
170 // 0 ... all parameters valid
171 // 1 ... priority exceeded range
172 // 2 ... ext-sys-id exceeded range
173 // 3 ... invalid MAC address or invalid interface
174 // 4 ... other
176 int mops_create_bpdu_bid(struct mops * mp, int pri, int esi, char *mac, int bid_or_rid)
178 int i;
179 struct mops_ext_bpdu * pd = mp->p_desc;
180 u_int8_t rid[8];
181 u_int16_t p16;
183 if ((pri<0)||(pri>15)) return 1;
184 if ((esi<0)||(esi>4095)) return 2;
186 if (mac!=NULL) {
187 // first check if an interface is specified:
188 i = mops_get_device_index(mac);
189 if (i!=-1) { // found
190 memcpy((void*) &rid[2], (void*) device_list[i].mac_mops, 6);
192 else { // MAC address given?
193 if (mops_pdesc_mac(&rid[2], mac)) {
194 return 3;
197 } else { // mac==NULL
198 // use MAC of default interface!
199 i = mops_get_device_index(tx.device);
200 if (i!=-1) { // found
201 memcpy((void*) &rid[2], (void*) device_list[i].mac_mops, 6);
203 else {
204 str2hex("00:00:00:00:00:00", &rid[2], 6);
205 return 4;
209 // now prepend pri, esi
211 p16 = pri;
212 p16 <<= 12;
213 p16 |= esi;
215 mops_hton2 (&p16, &rid[0]);
216 if (bid_or_rid)
217 memcpy((void*) pd->root_id, (void*) rid, 8);
218 else
219 memcpy((void*) pd->bridge_id, (void*) rid, 8);
220 return 0;
224 int mops_create_bpdu_trailer (struct mops * mp, u_int16_t vlan)
226 struct mops_ext_bpdu * pd = mp->p_desc;
228 // PVST+ requires a trailer with either all-zero
229 // or 00:00:00:00:02:VLAN(16bit)
231 // trailer already initialized with zeroes
232 pd->trailer[0]=0x00;
233 pd->trailer[1]=0x00;
234 pd->trailer[2]=0x00;
235 pd->trailer[3]=0x00;
236 pd->trailer[4]=0x02;
237 pd->trailer[5]=0x00;
238 pd->trailer[6]=0x00;
239 mops_hton2 (&vlan, &pd->trailer[5]);
241 return 0;