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
26 // Initialization function - specify defaults here!
28 int mops_init_pdesc_lldp(struct mops
*mp
)
30 struct mops_ext_lldp
* pd
;
33 if (mp
->p_desc
== NULL
) return 1; // p_desc not properly assigned
36 mp
->eth_type
= 0x88cc;
37 str2hex("01:80:c2:00:00:0e", mp
->eth_dst
, 6);
38 mp
->ndelay
.tv_sec
= 30;
39 mp
->ndelay
.tv_nsec
= 0;
41 // get interface index for that packet
42 i
= mops_get_device_index(mp
->device
);
45 pd
->chassis_id_subtype
= 4; // MAC address
46 if (pd
->chassis_id
==NULL
) pd
->chassis_id
= malloc(255);
47 if (pd
->chassis_id
==NULL
) return 1;
48 memcpy((void*) pd
->chassis_id
, (void*) device_list
[i
].mac_mops
, 6);
49 pd
->chassis_id_len
= 6;
50 pd
->port_id_subtype
= 5; // interface name
51 pd
->port_id_len
= strnlen(mp
->device
, 15);
52 if (pd
->port_id
==NULL
) pd
->port_id
= malloc(255);
53 if (pd
->port_id
==NULL
) return 1;
54 memcpy((void*) pd
->port_id
, (void*) mp
->device
, pd
->port_id_len
);
56 pd
->optional_tlvs_s
= 0;
57 if (pd
->optional_tlvs
==NULL
) pd
->optional_tlvs
= malloc(MAX_LLDP_OPT_TLVS
);
58 if (pd
->optional_tlvs
== NULL
) return 1;
64 int mops_update_lldp (struct mops
* mp
)
66 struct mops_ext_lldp
* pd
;
69 if (pd
==NULL
) return 1; // no valid pointer to a p_desc
70 mp
->msg_s
= 0; // important! Otherwise the msg would get longer and longer after each call!
72 switch (pd
->non_conform
) {
74 case 0: // Derive mandatory TLVs from struct entries and insert optional_tlvs
75 mp
->msg_s
+= mops_lldp_tlv_chassis(mp
->msg
,
76 pd
->chassis_id_subtype
,
79 mp
->msg_s
+= mops_lldp_tlv_port(&mp
->msg
[mp
->msg_s
],
83 mp
->msg_s
+= mops_lldp_tlv_TTL(&mp
->msg
[mp
->msg_s
],
85 if (pd
->optional_tlvs_s
) {
86 memcpy((void*) &mp
->msg
[mp
->msg_s
],
87 (void*) pd
->optional_tlvs
,
89 mp
->msg_s
+= pd
->optional_tlvs_s
;
91 mp
->msg_s
+= mops_lldp_tlv_end(&mp
->msg
[mp
->msg_s
]);
94 case 1: // User defined ALL TLVs (i. e. ignore struct entries)
95 if (pd
->optional_tlvs_s
) {
96 memcpy((void*) &mp
->msg
[mp
->msg_s
],
97 (void*) pd
->optional_tlvs
,
99 mp
->msg_s
+= pd
->optional_tlvs_s
;
101 mp
->msg_s
+= mops_lldp_tlv_end(&mp
->msg
[mp
->msg_s
]);
110 ///////////////////////////////////////////////////////////////////////////////
112 // Below are utility functions to creade the LLDPU. From these, the //
113 // following can be used for the optional part: //
121 int mops_lldp_opt_tlv (struct mops *mp, int type, int len, u_int8_t *value)
122 int mops_lldp_opt_tlv_chassis (struct mops *mp, int subtype, int len, u_int8_t *cid)
123 int mops_lldp_opt_tlv_port (struct mops *mp, int subtype, int len, u_int8_t *pid)
124 int mops_lldp_opt_tlv_TTL (struct mops *mp, int ttl)
125 int mops_lldp_opt_tlv_vlan (struct mops *mp, int vlan)
126 int mops_lldp_opt_tlv_end (struct mops *mp)
127 int mops_lldp_opt_tlv_bad (struct mops *mp, int type, int badlen, int len, u_int8_t *value)
128 int mops_lldp_opt_tlv_org (struct mops *mp, int oui, int subtype, int len, u_int8_t *inf)
141 ///////////////////////////////////////////////////////////////////////////////
147 // Creates a LLDP TLV for a given type number and value string. The result will
148 // be written into 'tlv'.
150 // NOTE: len must be given and indicates the length of value.
152 // RETURN VALUE: - Total number of bytes of this tlv
155 int mops_lldp_tlv (u_int8_t
*tlv
, int type
, int len
, u_int8_t
*value
)
157 u_int16_t tl
=0, tln
=0;
159 if ((type
>127) || (len
>511)) return 0;
165 memcpy((void*) tlv
, (void*) &tln
, 2);
166 memcpy((void*) &tlv
[2], (void*) value
, len
);
172 // Same as above but **adds the TLVs to the 'pd->optional_tlvs' string.**
173 // It also checks if MAX_LLDP_OPT_TLVS is exceeded.
175 // NOTE: first argument is a pointer to that mops!
177 // RETURN VALUE: - 0 upon error (no more space)
178 // - Total number of bytes written
180 int mops_lldp_opt_tlv (struct mops
* mp
, int type
, int len
, u_int8_t
*value
)
182 struct mops_ext_lldp
* pd
;
183 u_int8_t tmp
[MAX_LLDP_OPT_TLVS
]; // this *must* be sufficient in length
186 if (mp
->p_desc
== NULL
) return 1; // p_desc not properly assigned
189 l
= mops_lldp_tlv (tmp
, type
, len
, value
);
191 if ((MAX_LLDP_OPT_TLVS
- pd
->optional_tlvs_s
)< (l
+1)) return -1; // not enough space
192 memcpy((void*) (pd
->optional_tlvs
+ pd
->optional_tlvs_s
), (void*) tmp
, l
);
193 pd
->optional_tlvs_s
+= l
;
198 ///////////////////////////////////////////////////////////////////////////////
202 ///////////////////////////////////////////////////////////////////////////////
206 // Creates a Chassis ID TLV -- the first mandatory TLV.
207 // The result will be written into 'tlv'.
209 // RETURN VALUE: - Total number of bytes within tlv
212 int mops_lldp_tlv_chassis (u_int8_t
*tlv
, int subtype
, int len
, u_int8_t
*cid
)
216 if ((len
>255) || (subtype
>255)) return 0;
218 tmp
[0] = (u_int8_t
) subtype
;
219 memcpy((void*) (tmp
+1), (void*) cid
, len
);
220 return mops_lldp_tlv(tlv
, 1, len
+1, tmp
);
224 // Same but for optional tlv string
225 int mops_lldp_opt_tlv_chassis (struct mops
*mp
, int subtype
, int len
, u_int8_t
*cid
)
229 if ((len
>255) || (subtype
>255)) return 0;
230 tmp
[0] = (u_int8_t
) subtype
;
231 memcpy((void*) (tmp
+1), (void*) cid
, len
);
232 return mops_lldp_opt_tlv(mp
, 1, len
+1, tmp
);
237 ///////////////////////////////////////////////////////////////////////////////
241 ///////////////////////////////////////////////////////////////////////////////
245 // Creates a Port ID TLV -- the second mandatory TLV.
246 // The result will be written into 'tlv'.
248 // RETURN VALUE: - Total number of bytes within tlv
251 int mops_lldp_tlv_port (u_int8_t
*tlv
, int subtype
, int len
, u_int8_t
*pid
)
255 if ((len
>255) || (subtype
>255)) return 0;
257 tmp
[0] = (u_int8_t
) subtype
;
258 memcpy((void*) (tmp
+1), (void*) pid
, len
);
259 return mops_lldp_tlv(tlv
, 2, len
+1, tmp
);
262 // Same but for optional tlv string
263 int mops_lldp_opt_tlv_port (struct mops
*mp
, int subtype
, int len
, u_int8_t
*pid
)
267 if ((len
>255) || (subtype
>255)) return 0;
268 tmp
[0] = (u_int8_t
) subtype
;
269 memcpy((void*) (tmp
+1), (void*) pid
, len
);
270 return mops_lldp_opt_tlv(mp
, 2, len
+1, tmp
);
274 ///////////////////////////////////////////////////////////////////////////////
278 ///////////////////////////////////////////////////////////////////////////////
281 // Creates a TTL TLV -- the third mandatory TLV.
282 // The result will be written into 'tlv'.
284 // RETURN VALUE: - Total number of bytes within tlv
287 int mops_lldp_tlv_TTL (u_int8_t
*tlv
, int ttl
)
289 u_int16_t ttlh
=0, ttln
=0;
291 if (ttl
>0xffff) return 0;
293 ttlh
= (u_int16_t
) ttl
;
296 return mops_lldp_tlv(tlv
, 3, 2, (u_int8_t
*) &ttln
);
300 // Same but for optional tlv string
301 int mops_lldp_opt_tlv_TTL (struct mops
*mp
, int ttl
)
303 u_int16_t ttlh
=0, ttln
=0;
305 if (ttl
>0xffff) return 0;
307 ttlh
= (u_int16_t
) ttl
;
310 return mops_lldp_opt_tlv(mp
, 3, 2, (u_int8_t
*) &ttln
);
313 ///////////////////////////////////////////////////////////////////////////////
317 ///////////////////////////////////////////////////////////////////////////////
320 // Creates an End of LLDPDU TLV -- the last mandatory TLV.
321 // The result will be written into 'tlv'.
323 // RETURN VALUE: - Total number of bytes within tlv
326 int mops_lldp_tlv_end (u_int8_t
*tlv
)
333 // Same but for optional tlv string
334 int mops_lldp_opt_tlv_end (struct mops
*mp
)
336 struct mops_ext_lldp
* pd
;
338 if (mp
->p_desc
== NULL
) return 1; // p_desc not properly assigned
341 if ((MAX_LLDP_OPT_TLVS
- pd
->optional_tlvs_s
) > 2) {
342 pd
->optional_tlvs
[pd
->optional_tlvs_s
++] = 0x00;
343 pd
->optional_tlvs
[pd
->optional_tlvs_s
++] = 0x00;
350 ///////////////////////////////////////////////////////////////////////////////
354 ///////////////////////////////////////////////////////////////////////////////
357 // Creates a 'bad' LLDP TLV for a given type number and value string.
358 // The result will be appended into 'pd->optional_tlvs'
360 // NOTE: 'len' must be given and indicates the TRUE length of value.
361 // 'badlen' can be any number and is used as official length within the TLV
363 // RETURN VALUE: - Total number of bytes within tlv
366 int mops_lldp_opt_tlv_bad (struct mops
*mp
,
372 u_int16_t tl
=0, tln
=0;
374 struct mops_ext_lldp
* pd
= mp
->p_desc
;
376 if ((type
>127) || (len
>511) || (badlen
>511)) return 0;
377 if ((MAX_LLDP_OPT_TLVS
- pd
->optional_tlvs_s
) < (len
+3)) return 0;
383 memcpy((void*) tlv
, (void*) &tln
, 2);
384 memcpy((void*) &tlv
[2], (void*) value
, len
);
385 // this detour has historical reasons ;-)
386 memcpy((void*) (pd
->optional_tlvs
+ pd
->optional_tlvs_s
), (void*) tlv
, len
+2);
387 pd
->optional_tlvs
+= len
+2;
394 // Creates a Organisational-specific TLV -- the second mandatory TLV.
395 // The result will be appended into 'pd->optional_tlvs'
397 // RETURN VALUE: - Total number of bytes within tlv
400 int mops_lldp_opt_tlv_org (struct mops
*mp
,
408 u_int32_t oui_n
= (u_int32_t
) oui
;
410 if ((len
>507) || (subtype
>255) || (oui_n
>0xffffff)) return 0;
412 x
= (u_int8_t
*) &oui_n
;
416 tmp
[3] = (u_int8_t
) subtype
;
417 memcpy((void*) (tmp
+4), (void*) inf
, len
);
418 return mops_lldp_opt_tlv(mp
, 127, len
+4, tmp
);
422 int mops_lldp_opt_tlv_vlan (struct mops
*mp
,
426 if (vlan
>0xffff) return 0; // yes, we also allow VLAN IDs > 4095
428 return mops_lldp_opt_tlv_org (mp
, 0x80c2, 1, 2, (u_int8_t
*) &vid
);