mausezahn: use getopt_long instead of getopt
[netsniff-ng.git] / staging / layer2.c
blob3a48820a8b4b30206c099629c9f9665a191357bd
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 // ***************************************************************************
22 // This sections contains functions to send various L2-based PDUs such as
23 // * ARP
24 // * BPDU
25 // ***************************************************************************
27 #include "mz.h"
28 #include "cli.h"
32 #define MZ_ARP_HELP \
33 "| ARP type: Send arbitrary ARP packets.\n" \
34 "| Note:\n" \
35 "| - The Ethernet dst and src MAC addresses can be specified but can be also 'rand'.\n" \
36 "| - If dst and src are NOT specified then practical defaults are used (src=own MAC, dst=bc).\n" \
37 "|\n" \
38 "| ARGUMENT SYNTAX: <command> [<parameters>]\n" \
39 "| | |\n" \
40 "| help, request, reply --+ |\n" \
41 "| +-- sendermac, senderip, targetmac, targetip\n" \
42 "| smac sip tmac tip\n" \
43 "|\n" \
44 "| EXAMPLES:\n" \
45 "| 1. Legitimate ARP response to broadcast:\n" \
46 "| # mz eth0 -t arp \"reply\"\n" \
47 "| 2. ARP cache poisoning, claiming to be 192.168.0.1, telling a target PC:\n" \
48 "| # mz eth0 -t arp \"reply, senderip=192.168.0.1, targetmac=00:00:0c:01:02:03, targetip=172.16.1.50\"\n" \
49 "\n"
52 #define MZ_BPDU_HELP \
53 "| BPDU type: Send arbitrary BPDU packets (spanning tree).\n" \
54 "|\n" \
55 "| ARGUMENT SYNTAX: <command> [<parameters>]\n" \
56 "| | \n" \
57 "| conf, tcn --+ \n" \
58 "| \n" \
59 "| Parameters:\n" \
60 "|\n" \
61 "| id = 0-65535 ..... default: 0, identifies 'Spanning Tree Protocol'\n" \
62 "| version = 0-255 ..... default: 0\n" \
63 "| type = 0-255 ..... BPDU Type: 0=CONF, 1=TCN (default: CONF)\n" \
64 "| flags = 0-255 ..... 1=TC, 128=ACK (default: 0 = No TC, No ACK)\n" \
65 "| rootid = <pri>:<mac> ..... 8 byte Root-ID (default: 00:00:<own-mac>)\n" \
66 "| rootpc = 0-4294967295 ..... root path cost (default: 0)\n" \
67 "| bid = <mac> ..... 6 byte MAC address (default: own-mac)\n" \
68 "| pid = 0-65535 ..... port identifier (default: 0)\n" \
69 "| age = 0-65535 ..... message age (default: 0)\n" \
70 "| maxage = 0-65535 ..... max age (default: 20)\n" \
71 "| hello = 0-65535 ..... hello time (default: 2)\n" \
72 "| fwd = 0-65535 ..... forward delay (default: 15)\n" \
73 "| tag - ..... Keyword to enforce 802.1Q VLAN tag; use this\n" \
74 "| together with the 'vlan' parameter below.\n" \
75 "|\n" \
76 "| PVST+ extensions:\n" \
77 "|\n" \
78 "| vlan ..... VLAN number (default: 0)\n" \
79 "| pri ..... 802.1P-Priority (0-7, default: 0)\n" \
80 "| notag ..... Omit 802.1Q VLAN tag\n" \
81 "| \n" \
82 "|\n" \
83 "| DEFAULTS: mz sends standard IEEE 802.1d (CST) BPDUs and assumes that your computer\n" \
84 "| wants to become the root bridge (rid=bid). Configuration BPDUs are the default but\n" \
85 "| can be changed using the 'tcn' keyword. Optionally the 802.3 source and destination\n" \
86 "| MAC addresses can be specified using the -a and -b options. Per default, the correct\n" \
87 "| STP or PVST+ destination addresses are used (same as '-b stp' or '-b pvst', \n" \
88 "| respectively).\n" \
89 "| \n" \
90 "| Note that the parameter 'vlan' only selects the PVST+ mode if the parameter 'tag' is\n" \
91 "| NOT used.\n" \
92 "\n"
96 // Send arbitrary ARP packets.
97 // Note:
98 // - The Ethernet dst and src MAC addresses can be specified,
99 // the eth_src_txt can be 'rand'
100 // - If eth_dst and eth_src are NOT specified then practical defaults are used
102 // arg_string syntax: <command>, <param>, ... , <param>
103 // - commands: 'request' OR 'reply'
104 // - params: 'sendermac', 'senderip', 'targetmac', 'targetip'
106 // Example arg_string for ARP cache poisoning:
107 // "reply, senderip=192.168.0.1, targetmac=00:00:0c:01:02:03, targetip=172.16.1.50"
108 // where sendermac will be automatically replaced by own mac,
109 // senderip is the spoofed IP,
110 // targetmac and targetip identifies the receiver.
112 int send_arp(void)
114 libnet_t *l;
115 libnet_ptag_t t;
117 char
118 argval[64],
119 t1[64],
120 t2[64],
121 src,
122 dst,
123 errbuf[LIBNET_ERRBUF_SIZE];
125 int
127 arpmode=0,
128 arpop=0,
129 loop,
130 tm=0;
132 u_int8_t
133 *packet,
134 sendermac[6],
135 targetmac[6];
139 u_int32_t
140 packet_s,
141 senderip=0,
142 targetip=0;
145 if (tx.dot1Q)
147 fprintf(stderr," Note: ARP mode does not support 802.1Q builder.\n");
148 exit(1);
151 if (tx.mpls)
153 fprintf(stderr," Note: ARP mode does not support MPLS builder.\n");
154 exit(1);
157 if (getarg(tx.arg_string,"help", NULL)==1)
159 if (mz_port)
161 cli_print(gcli, "%s", MZ_ARP_HELP);
162 return -1;
164 else
166 fprintf(stderr,"\n"
167 MAUSEZAHN_VERSION
168 "\n%s", MZ_ARP_HELP);
169 exit(0);
174 // Set the flags to shorten subsequent decisions:
175 src = strlen(tx.eth_src_txt);
176 dst = strlen(tx.eth_dst_txt);
178 l = libnet_init(LIBNET_LINK_ADV, tx.device, errbuf);
180 if (l == NULL)
182 fprintf(stderr, "%s", errbuf);
183 exit(EXIT_FAILURE);
188 if (getarg(tx.arg_string,"request", NULL)==1)
190 arpmode=1;
191 arpop = ARPOP_REQUEST;
193 else
194 if (getarg(tx.arg_string, "reply", NULL)==1)
196 arpmode=2;
197 arpop = ARPOP_REPLY;
199 else
200 { // Default:
201 arpmode=2;
202 arpop = ARPOP_REPLY;
207 if ( (getarg(tx.arg_string,"sendermac", argval)==1) || (getarg(tx.arg_string,"smac", argval)==1) )
209 //TODO: Allow 'rand' as sendermac
210 str2hex(argval,sendermac,6);
212 else
214 // sendermac is usually ALWAYS own MAC:
215 getbytes(tx.eth_src, sendermac,1,6);
219 if ( (getarg(tx.arg_string,"targetmac", argval)==1) || (getarg(tx.arg_string,"tmac", argval)==1) )
221 str2hex(argval,targetmac,6);
222 tm=1;
224 else
226 // targetmac is either zero (request) or bcast (reply=>gratitious ARP)
227 if (arpmode==1) //request
228 str2hex("00:00:00:00:00:00",targetmac, 6);
229 else //reply
230 str2hex("ff:ff:ff:ff:ff:ff",targetmac, 6);
234 if ( (getarg(tx.arg_string,"senderip", argval)==1) || (getarg(tx.arg_string,"sip", argval)==1) )
236 senderip = str2ip32_rev(argval);
238 else
240 // senderip is usually ALWAYS the own IP
241 senderip = libnet_get_ipaddr4(l); // TODO - use tx.ip_src
246 if ( (getarg(tx.arg_string,"targetip", argval)==1) || (getarg(tx.arg_string,"tip", argval)==1) )
248 targetip = str2ip32_rev(argval);
250 else
252 // if targetip is missing also use own IP because it may be used for duplicate IP detection
253 targetip = libnet_get_ipaddr4(l);
258 // NOTE: Now all ARP parameters are set (possibly defaults used!)
260 bs2str(sendermac,t1,6);
261 bs2str(targetmac,t2,6);
262 //Check:
263 //printf("-- sendermac=%s targetmac=%s senderip=%u targetip=%u\n",t1,t2,senderip,targetip);
267 // Build the ARP header
269 t = libnet_autobuild_arp(arpop, /* operation type */
270 sendermac, /* sender hardware addr */
271 (u_int8_t *)&senderip, /* sender protocol addr */
272 targetmac, /* target hardware addr */
273 (u_int8_t *)&targetip, /* target protocol addr */
274 l); /* libnet context */
276 if (t == -1)
278 fprintf(stderr, " mz/send_arp: Can't build ARP header: %s\n", libnet_geterror(l));
279 exit(EXIT_FAILURE);
283 // Finally build the Ethernet header
285 if ((!dst) && (!src)) // ... user does not care about addresses (both eth_dst and eth_src NOT specified)
287 if (arpmode==1)
288 str2hex("ff:ff:ff:ff:ff:ff", tx.eth_dst, 6);
289 else
290 getbytes(targetmac, tx.eth_dst, 1, 6); // either also bcast or specific MAC
292 t = libnet_autobuild_ethernet(tx.eth_dst, /* ethernet destination */
293 ETHERTYPE_ARP, /* protocol type */
294 l); /* libnet handle */
296 if (t == -1)
298 fprintf(stderr, " mz/send_arp: Can't build ethernet header: %s\n",
299 libnet_geterror(l));
300 exit(EXIT_FAILURE);
303 else // EITHER eth_dst OR eth_src OR BOTH specified:
305 if (!dst)
307 if (arpmode==1)
308 str2hex("ff:ff:ff:ff:ff:ff", tx.eth_dst, 6);
309 else
310 getbytes(targetmac, tx.eth_dst, 1, 6); // either also bcast when reply or specific MAC
312 else // eth_dst specified
314 if (check_eth_mac_txt(ETH_DST)) // if true then problem!
316 str2hex("ff:ff:ff:ff:ff:ff",tx.eth_dst, 6); // the default
321 if (!src)
323 // tx.eth_src contains own MAC by default!
325 else // use specified source MAC address
327 if (check_eth_mac_txt(ETH_SRC)) // if true then problem!
329 str2hex("ff:ff:ff:ff:ff:ff",tx.eth_src, 6); // the default
333 t = libnet_build_ethernet (tx.eth_dst, tx.eth_src, ETHERTYPE_ARP, NULL, 0, l, 0); // Note: payload=NULL, payload_s=0
336 if (libnet_adv_cull_packet(l, &packet, &packet_s) == -1)
338 fprintf(stderr, "%s", libnet_geterror(l));
340 else
342 libnet_adv_free_packet(l, packet);
345 // this is for the statistics:
346 mz_start = clock();
347 total_d = tx.count;
350 again:
352 if (tx.count==0)
353 loop=1000000;
354 else
355 loop=tx.count;
357 for (i=1; i<=loop; i++)
360 if (!simulate) libnet_write(l);
362 if (verbose)
364 fprintf(stderr," sent ARP: %s smac=%s sip=%s tmac=%s tip=%s\n",
365 (arpmode==1) ? "request" : "reply",
367 libnet_addr2name4(senderip,LIBNET_DONT_RESOLVE),
369 libnet_addr2name4(targetip,LIBNET_DONT_RESOLVE));
373 if (tx.delay) SLEEP (tx.delay);
376 if (tx.count==0)
378 goto again;
382 libnet_destroy(l);
384 return 0;
401 ///////////////////////////////////////////////////////////////////////////////////////
402 // Send arbitrary BPDU frames.
404 // commands:
405 // conf|tcn ...when specifying everything yourself
407 // params:
408 // id, version, type, flags, rootid, rootpc, bid, pid, age, maxage, hello, fwd,
409 // vlan
411 // defaults:
412 // mz assumes you want to become root bridge! (rid=bid)
413 int send_bpdu(void) {
415 // BPDU parameters:
416 u_int16_t
417 id=0;
418 u_int8_t
419 version=0,
420 bpdu_type=0, // 0=conf, 1=topology change (actually in big endian!)
421 flags=0, // 1=TC, 128=TCAck
422 root_id[8], // Root BID
423 bridge_id[8]; // Own BID
424 u_int32_t
425 root_pc=0; // Root Path Cost
426 u_int16_t
427 port_id=0, // Port Identifier
428 message_age=0, // All timers are multiples of 1/256 sec. Thus times range from 0 to 256 seconds.
429 max_age=20,
430 hello_time=2, //
431 f_delay=15;
433 // LLC Parameters:
434 u_int8_t
435 dsap=0x42,
436 ssap=0x42,
437 control=0x3;
439 // Optional payload (needed for PVST+)
440 u_int8_t
441 bpdu_payload[64],
442 snap_oui[3];
443 u_int32_t
444 bpdu_payload_s=0;
445 u_int16_t
446 vlan=0;
447 u_int8_t
448 priority=0x00,
450 int
451 tag=0;
454 // Standard libnet variables:
455 libnet_t *l;
456 libnet_ptag_t t;
457 char errbuf[LIBNET_ERRBUF_SIZE];
459 // Other variables:
460 unsigned int i, loop;
461 int bpdumode=0;
462 char argval[64];
463 char dum1[32], dum2[32];
466 if (tx.dot1Q)
468 fprintf(stderr," Note: BPDU mode does not support 802.1Q builder.\n");
469 exit(1);
472 if (tx.mpls)
474 fprintf(stderr," Note: BPDU mode does not support MPLS builder.\n");
475 exit(1);
479 // HELP TEXT
480 if (getarg(tx.arg_string,"help", NULL)==1)
482 if (mz_port)
484 cli_print(gcli, "%s", MZ_BPDU_HELP);
485 return -1;
487 else
489 fprintf(stderr,"\n"
490 MAUSEZAHN_VERSION
491 "\n%s", MZ_BPDU_HELP);
492 exit(0);
496 /////////////////////////////////////////////////////////
497 // Default Destination Address
498 if (check_eth_mac_txt(ETH_DST)) // if true then problem!
500 str2hex("01:80:C2:00:00:00",tx.eth_dst, 6); // if '1' then user did not set MAC address (or problem occurred)
503 // Default Bridge-ID
504 bridge_id[0]=0x00;
505 bridge_id[1]=0x00;
506 for (i=0; i<6; i++) bridge_id[2+i]=tx.eth_src[i];
507 for (i=0; i<8; i++) root_id[i]=bridge_id[i];
508 /////////////////////////////////////////////////////////
513 // determine BPDU type:
514 if (getarg(tx.arg_string,"conf", NULL)==1)
516 bpdumode=1;
517 tx.eth_len = LIBNET_802_2_H + LIBNET_STP_CONF_H;
519 else
520 if (getarg(tx.arg_string, "tcn", NULL)==1)
522 bpdumode=2;
523 tx.eth_len = LIBNET_802_2_H + LIBNET_STP_TCN_H;
524 bpdu_type=0x80;
526 else // default
528 bpdumode=1;
529 tx.eth_len = LIBNET_802_2_H + LIBNET_STP_CONF_H;
533 // Commands summary:
534 // id, version, type, flags, rid, rootpc, bid, pid, age, maxage, hello, fwd
536 if (getarg(tx.arg_string,"id", argval)==1)
538 id = (u_int16_t) str2int(argval);
541 if (getarg(tx.arg_string,"version", argval)==1)
543 version = (u_int8_t) str2int(argval);
546 if (getarg(tx.arg_string,"bpdu_type", argval)==1)
548 bpdu_type = (u_int8_t) str2int(argval);
551 if (getarg(tx.arg_string,"flags", argval)==1)
553 flags = (u_int8_t) str2int(argval);
556 if (getarg(tx.arg_string,"rid", argval)==1)
558 if (str2hex(argval,root_id, 8)!=8)
560 fprintf(stderr," mz/send_bpdu: [ERROR] The root-id must be exactly 8 bytes!\n");
561 exit (-1);
565 if (getarg(tx.arg_string,"rootpc", argval)==1)
567 root_pc = (u_int32_t) str2int(argval);
570 if (getarg(tx.arg_string,"bid", argval)==1)
572 if (str2hex(argval,bridge_id, 6)!=6)
574 fprintf(stderr," mz/send_bpdu: [ERROR] The bridge-id must be exactly 6 bytes!\n");
575 exit (-1);
579 if (getarg(tx.arg_string,"pid", argval)==1)
581 port_id = (u_int16_t) str2int(argval);
584 if (getarg(tx.arg_string,"age", argval)==1)
586 message_age = (u_int16_t) str2int(argval);
589 if (getarg(tx.arg_string,"maxage", argval)==1)
591 max_age = (u_int16_t) str2int(argval);
594 if (getarg(tx.arg_string,"hello", argval)==1)
596 hello_time = (u_int16_t) str2int(argval);
599 if (getarg(tx.arg_string,"fwd", argval)==1)
601 f_delay = (u_int16_t) str2int(argval);
606 if (getarg(tx.arg_string,"vlan", argval)==1)
608 // PVST+ uses TLVs of type=0x00, len=0x02, and Value=0xVV which is the VLAN ID
609 // The DA must be 0100.0ccc.cccd instead of the standard 0180.c200.0000
611 if (check_eth_mac_txt(ETH_DST)) // if '1' then user did not set MAC address (or problem occurred)
613 str2hex("01:00:0C:CC:CC:CD",tx.eth_dst, 6); // Cisco PVST+ address
616 /* // OLD TLV, maybe wrong, maybe obsolete, I don't know.
618 bpdu_payload[0] = 0x34;
619 bpdu_payload[1] = 0x00;
620 bpdu_payload[2] = 0x02;
621 vlan = (u_int16_t) str2int(argval);
623 x = (u_int8_t*) &vlan;
624 bpdu_payload[3] = *(x+1);
625 bpdu_payload[4] = *(x);
626 bpdu_payload[5] = 0x00;
627 bpdu_payload[6] = 0x00;
628 bpdu_payload_s = 7;
630 // Updated PVST+ TLV:
631 bpdu_payload[0] = 0x00;
632 bpdu_payload[1] = 0x00;
633 bpdu_payload[2] = 0x00;
634 bpdu_payload[3] = 0x00;
635 bpdu_payload[4] = 0x02;
636 vlan = (u_int16_t) str2int(argval);
637 x = (u_int8_t*) &vlan;
638 bpdu_payload[5] = *(x+1);
639 bpdu_payload[6] = *(x);
640 bpdu_payload_s = 7;
642 tag=1; // set the default: Use 802.1Q tag !!!
644 else // even a normal BPDU must be padded to 60 bytes (total)
646 bpdu_payload[0] = 0x00;
647 bpdu_payload[1] = 0x00;
648 bpdu_payload[2] = 0x00;
649 bpdu_payload[3] = 0x00;
650 bpdu_payload[4] = 0x00;
651 bpdu_payload[5] = 0x00;
652 bpdu_payload[6] = 0x00;
653 bpdu_payload[7] = 0x00;
654 bpdu_payload_s = 8;
656 tag=0; // set the default: send untagged !!!
660 // Note: The order is important because above the defaults for 'tag' has been set.
662 if (getarg(tx.arg_string,"notag", NULL)==1)
664 tag=0;
668 // Send normal BPDU with VLAN tag
669 if (getarg(tx.arg_string,"tag", NULL)==1)
671 tag=2;
672 bpdu_payload[0] = 0x00;
673 bpdu_payload[1] = 0x00;
674 bpdu_payload[2] = 0x00;
675 bpdu_payload[3] = 0x00;
676 bpdu_payload[4] = 0x00;
677 bpdu_payload[5] = 0x00;
678 bpdu_payload[6] = 0x00;
679 bpdu_payload[7] = 0x00;
680 bpdu_payload_s = 8;
682 // Rewrite to standard 0180.c200.0000
684 if (check_eth_mac_txt(ETH_DST)) // if '1' then user did not set MAC address (or problem occurred)
686 str2hex("01:80:C2:00:00:00",tx.eth_dst, 6);
688 vlan = (u_int16_t) str2int(argval);
692 if (getarg(tx.arg_string,"pri", argval)==1)
694 priority = (u_int8_t) str2int(argval);
695 if (priority>7)
697 fprintf(stderr, " mz/send_bpdu: Priority must be between 0 and 7.\n");
698 exit(1);
701 if (tag==0)
703 fprintf(stderr, " mz/send_bpdu: Priority cannot be used together with the 'notag' keyword.\n");
704 exit(1);
709 // Open the link - get libnet handle
710 l = libnet_init(LIBNET_LINK_ADV, tx.device, errbuf);
712 if (l == NULL)
714 fprintf(stderr, "%s", errbuf);
715 exit(EXIT_FAILURE);
719 if (bpdumode==1) // Prepare CONFIGURATION BPDU:
722 t = libnet_build_stp_conf (id,
723 version,
724 bpdu_type,
725 flags,
726 root_id,
727 root_pc,
728 bridge_id,
729 port_id,
730 message_age,
731 max_age,
732 hello_time,
733 f_delay,
734 (bpdu_payload_s) ? bpdu_payload : NULL,
735 bpdu_payload_s,
739 if (t == -1)
741 fprintf(stderr, " mz/send_bpdu: Can't build BPDU header: %s\n",
742 libnet_geterror(l));
743 exit(EXIT_FAILURE);
746 else // Topology Change BPDU
748 t = libnet_build_stp_tcn(id,
749 version,
750 bpdu_type,
751 (bpdu_payload_s) ? bpdu_payload : NULL,
752 bpdu_payload_s,
754 0);
755 if (t == -1)
758 fprintf(stderr, " mz/send_bpdu: Can't build BPDU header: %s\n",
759 libnet_geterror(l));
760 exit(EXIT_FAILURE);
766 if ( (vlan==0) || (tag==2) ) // normal BPDU
768 // normal LLC without SNAP
769 t = libnet_build_802_2 (dsap,
770 ssap,
771 control,
772 NULL,
777 if (t == -1)
779 fprintf(stderr, " mz/send_bpdu: Can't build LLC header: %s\n",
780 libnet_geterror(l));
781 exit(EXIT_FAILURE);
784 else // PVST+ => LLC with SNAP
786 snap_oui[0]=0x00;
787 snap_oui[1]=0x00;
788 snap_oui[2]=0x0c;
790 // requires a SNAP header with oui=0x00000c and type=0x010b
791 t = libnet_build_802_2snap(0xAA,
792 0xAA,
793 0x03,
794 snap_oui,
795 0x010b,
796 NULL,
801 if (t == -1)
803 fprintf(stderr, " mz/send_bpdu: Can't build SNAP header: %s\n",
804 libnet_geterror(l));
805 exit(EXIT_FAILURE);
810 if (tag==0)
812 // Normal 802.3 header without VLAN tag
813 t = libnet_build_802_3 (tx.eth_dst,
814 tx.eth_src,
815 (vlan) ? 0x36 : tx.eth_len, // NOTE the LENGTH field => 802.3 header!
816 NULL,
822 else // PVST+ => 802.3 with 802.1Q
824 t = libnet_build_802_1q(tx.eth_dst,
825 tx.eth_src,
826 0x8100,
827 priority,
828 0x00, // CFI
829 vlan,
830 0x32, //tx.eth_len,
831 NULL,
838 if (t == -1)
840 fprintf(stderr, " mz/send_bpdu: Can't build 802.3 header: %s\n",
841 libnet_geterror(l));
842 exit(EXIT_FAILURE);
846 // This is ugly but it works good ;-)
847 if (tx.count==0)
848 loop=1000000;
849 else
850 loop=tx.count;
852 // this is for the statistics:
853 mz_start = clock();
854 total_d = tx.count;
857 again:
859 for (i=1; i<=loop; i++)
861 if (!simulate) libnet_write(l);
863 if (verbose)
865 bs2str(root_id,dum1,8);
866 bs2str(bridge_id,dum2,8);
867 fprintf(stderr," sent BPDU: ");
868 fprintf(stderr,"%s ", (bpdumode==1) ? "conf" : "tcn ");
869 fprintf(stderr," id=%u ver=%u flags=%x rid=%s bid=%s\n"
870 " rpc=%u pid=%u age=%u maxage=%u hello=%u fwd_delay=%u\n",
871 id,
872 version,
873 flags,
874 dum1,
875 dum2,
876 root_pc,
877 port_id,
878 message_age,
879 max_age,
880 hello_time,
881 f_delay);
883 fprintf(stderr,"\n");
887 if (tx.delay) SLEEP (tx.delay);
890 if (tx.count==0)
892 goto again;
896 libnet_destroy(l);
898 return 0;