docs: update email address
[netsniff-ng.git] / src / layer2.c
blobebbc7d8fc18df0494470812b43854ebc7f8e24d0
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 ()
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)
414 int send_bpdu ()
417 // BPDU parameters:
418 u_int16_t
419 id=0;
420 u_int8_t
421 version=0,
422 bpdu_type=0, // 0=conf, 1=topology change (actually in big endian!)
423 flags=0, // 1=TC, 128=TCAck
424 root_id[8], // Root BID
425 bridge_id[8]; // Own BID
426 u_int32_t
427 root_pc=0; // Root Path Cost
428 u_int16_t
429 port_id=0, // Port Identifier
430 message_age=0, // All timers are multiples of 1/256 sec. Thus times range from 0 to 256 seconds.
431 max_age=20,
432 hello_time=2, //
433 f_delay=15;
435 // LLC Parameters:
436 u_int8_t
437 dsap=0x42,
438 ssap=0x42,
439 control=0x3;
441 // Optional payload (needed for PVST+)
442 u_int8_t
443 bpdu_payload[64],
444 snap_oui[3];
445 u_int32_t
446 bpdu_payload_s=0;
447 u_int16_t
448 vlan=0;
449 u_int8_t
450 priority=0x00,
452 int
453 tag=0;
456 // Standard libnet variables:
457 libnet_t *l;
458 libnet_ptag_t t;
459 char errbuf[LIBNET_ERRBUF_SIZE];
461 // Other variables:
462 unsigned int i, loop;
463 int bpdumode=0;
464 char argval[64];
465 char dum1[32], dum2[32];
468 if (tx.dot1Q)
470 fprintf(stderr," Note: BPDU mode does not support 802.1Q builder.\n");
471 exit(1);
474 if (tx.mpls)
476 fprintf(stderr," Note: BPDU mode does not support MPLS builder.\n");
477 exit(1);
481 // HELP TEXT
482 if (getarg(tx.arg_string,"help", NULL)==1)
484 if (mz_port)
486 cli_print(gcli, "%s", MZ_BPDU_HELP);
487 return -1;
489 else
491 fprintf(stderr,"\n"
492 MAUSEZAHN_VERSION
493 "\n%s", MZ_BPDU_HELP);
494 exit(0);
498 /////////////////////////////////////////////////////////
499 // Default Destination Address
500 if (check_eth_mac_txt(ETH_DST)) // if true then problem!
502 str2hex("01:80:C2:00:00:00",tx.eth_dst, 6); // if '1' then user did not set MAC address (or problem occurred)
505 // Default Bridge-ID
506 bridge_id[0]=0x00;
507 bridge_id[1]=0x00;
508 for (i=0; i<6; i++) bridge_id[2+i]=tx.eth_src[i];
509 for (i=0; i<8; i++) root_id[i]=bridge_id[i];
510 /////////////////////////////////////////////////////////
515 // determine BPDU type:
516 if (getarg(tx.arg_string,"conf", NULL)==1)
518 bpdumode=1;
519 tx.eth_len = LIBNET_802_2_H + LIBNET_STP_CONF_H;
521 else
522 if (getarg(tx.arg_string, "tcn", NULL)==1)
524 bpdumode=2;
525 tx.eth_len = LIBNET_802_2_H + LIBNET_STP_TCN_H;
526 bpdu_type=0x80;
528 else // default
530 bpdumode=1;
531 tx.eth_len = LIBNET_802_2_H + LIBNET_STP_CONF_H;
535 // Commands summary:
536 // id, version, type, flags, rid, rootpc, bid, pid, age, maxage, hello, fwd
538 if (getarg(tx.arg_string,"id", argval)==1)
540 id = (u_int16_t) str2int(argval);
543 if (getarg(tx.arg_string,"version", argval)==1)
545 version = (u_int8_t) str2int(argval);
548 if (getarg(tx.arg_string,"bpdu_type", argval)==1)
550 bpdu_type = (u_int8_t) str2int(argval);
553 if (getarg(tx.arg_string,"flags", argval)==1)
555 flags = (u_int8_t) str2int(argval);
558 if (getarg(tx.arg_string,"rid", argval)==1)
560 if (str2hex(argval,root_id, 8)!=8)
562 fprintf(stderr," mz/send_bpdu: [ERROR] The root-id must be exactly 8 bytes!\n");
563 exit (-1);
567 if (getarg(tx.arg_string,"rootpc", argval)==1)
569 root_pc = (u_int32_t) str2int(argval);
572 if (getarg(tx.arg_string,"bid", argval)==1)
574 if (str2hex(argval,bridge_id, 6)!=6)
576 fprintf(stderr," mz/send_bpdu: [ERROR] The bridge-id must be exactly 6 bytes!\n");
577 exit (-1);
581 if (getarg(tx.arg_string,"pid", argval)==1)
583 port_id = (u_int16_t) str2int(argval);
586 if (getarg(tx.arg_string,"age", argval)==1)
588 message_age = (u_int16_t) str2int(argval);
591 if (getarg(tx.arg_string,"maxage", argval)==1)
593 max_age = (u_int16_t) str2int(argval);
596 if (getarg(tx.arg_string,"hello", argval)==1)
598 hello_time = (u_int16_t) str2int(argval);
601 if (getarg(tx.arg_string,"fwd", argval)==1)
603 f_delay = (u_int16_t) str2int(argval);
608 if (getarg(tx.arg_string,"vlan", argval)==1)
610 // PVST+ uses TLVs of type=0x00, len=0x02, and Value=0xVV which is the VLAN ID
611 // The DA must be 0100.0ccc.cccd instead of the standard 0180.c200.0000
613 if (check_eth_mac_txt(ETH_DST)) // if '1' then user did not set MAC address (or problem occurred)
615 str2hex("01:00:0C:CC:CC:CD",tx.eth_dst, 6); // Cisco PVST+ address
618 /* // OLD TLV, maybe wrong, maybe obsolete, I don't know.
620 bpdu_payload[0] = 0x34;
621 bpdu_payload[1] = 0x00;
622 bpdu_payload[2] = 0x02;
623 vlan = (u_int16_t) str2int(argval);
625 x = (u_int8_t*) &vlan;
626 bpdu_payload[3] = *(x+1);
627 bpdu_payload[4] = *(x);
628 bpdu_payload[5] = 0x00;
629 bpdu_payload[6] = 0x00;
630 bpdu_payload_s = 7;
632 // Updated PVST+ TLV:
633 bpdu_payload[0] = 0x00;
634 bpdu_payload[1] = 0x00;
635 bpdu_payload[2] = 0x00;
636 bpdu_payload[3] = 0x00;
637 bpdu_payload[4] = 0x02;
638 vlan = (u_int16_t) str2int(argval);
639 x = (u_int8_t*) &vlan;
640 bpdu_payload[5] = *(x+1);
641 bpdu_payload[6] = *(x);
642 bpdu_payload_s = 7;
644 tag=1; // set the default: Use 802.1Q tag !!!
646 else // even a normal BPDU must be padded to 60 bytes (total)
648 bpdu_payload[0] = 0x00;
649 bpdu_payload[1] = 0x00;
650 bpdu_payload[2] = 0x00;
651 bpdu_payload[3] = 0x00;
652 bpdu_payload[4] = 0x00;
653 bpdu_payload[5] = 0x00;
654 bpdu_payload[6] = 0x00;
655 bpdu_payload[7] = 0x00;
656 bpdu_payload_s = 8;
658 tag=0; // set the default: send untagged !!!
662 // Note: The order is important because above the defaults for 'tag' has been set.
664 if (getarg(tx.arg_string,"notag", NULL)==1)
666 tag=0;
670 // Send normal BPDU with VLAN tag
671 if (getarg(tx.arg_string,"tag", NULL)==1)
673 tag=2;
674 bpdu_payload[0] = 0x00;
675 bpdu_payload[1] = 0x00;
676 bpdu_payload[2] = 0x00;
677 bpdu_payload[3] = 0x00;
678 bpdu_payload[4] = 0x00;
679 bpdu_payload[5] = 0x00;
680 bpdu_payload[6] = 0x00;
681 bpdu_payload[7] = 0x00;
682 bpdu_payload_s = 8;
684 // Rewrite to standard 0180.c200.0000
686 if (check_eth_mac_txt(ETH_DST)) // if '1' then user did not set MAC address (or problem occurred)
688 str2hex("01:80:C2:00:00:00",tx.eth_dst, 6);
690 vlan = (u_int16_t) str2int(argval);
694 if (getarg(tx.arg_string,"pri", argval)==1)
696 priority = (u_int8_t) str2int(argval);
697 if (priority>7)
699 fprintf(stderr, " mz/send_bpdu: Priority must be between 0 and 7.\n");
700 exit(1);
703 if (tag==0)
705 fprintf(stderr, " mz/send_bpdu: Priority cannot be used together with the 'notag' keyword.\n");
706 exit(1);
711 // Open the link - get libnet handle
712 l = libnet_init(LIBNET_LINK_ADV, tx.device, errbuf);
714 if (l == NULL)
716 fprintf(stderr, "%s", errbuf);
717 exit(EXIT_FAILURE);
721 if (bpdumode==1) // Prepare CONFIGURATION BPDU:
724 t = libnet_build_stp_conf (id,
725 version,
726 bpdu_type,
727 flags,
728 root_id,
729 root_pc,
730 bridge_id,
731 port_id,
732 message_age,
733 max_age,
734 hello_time,
735 f_delay,
736 (bpdu_payload_s) ? bpdu_payload : NULL,
737 bpdu_payload_s,
741 if (t == -1)
743 fprintf(stderr, " mz/send_bpdu: Can't build BPDU header: %s\n",
744 libnet_geterror(l));
745 exit(EXIT_FAILURE);
748 else // Topology Change BPDU
750 t = libnet_build_stp_tcn(id,
751 version,
752 bpdu_type,
753 (bpdu_payload_s) ? bpdu_payload : NULL,
754 bpdu_payload_s,
756 0);
757 if (t == -1)
760 fprintf(stderr, " mz/send_bpdu: Can't build BPDU header: %s\n",
761 libnet_geterror(l));
762 exit(EXIT_FAILURE);
768 if ( (vlan==0) || (tag==2) ) // normal BPDU
770 // normal LLC without SNAP
771 t = libnet_build_802_2 (dsap,
772 ssap,
773 control,
774 NULL,
779 if (t == -1)
781 fprintf(stderr, " mz/send_bpdu: Can't build LLC header: %s\n",
782 libnet_geterror(l));
783 exit(EXIT_FAILURE);
786 else // PVST+ => LLC with SNAP
788 snap_oui[0]=0x00;
789 snap_oui[1]=0x00;
790 snap_oui[2]=0x0c;
792 // requires a SNAP header with oui=0x00000c and type=0x010b
793 t = libnet_build_802_2snap(0xAA,
794 0xAA,
795 0x03,
796 snap_oui,
797 0x010b,
798 NULL,
803 if (t == -1)
805 fprintf(stderr, " mz/send_bpdu: Can't build SNAP header: %s\n",
806 libnet_geterror(l));
807 exit(EXIT_FAILURE);
812 if (tag==0)
814 // Normal 802.3 header without VLAN tag
815 t = libnet_build_802_3 (tx.eth_dst,
816 tx.eth_src,
817 (vlan) ? 0x36 : tx.eth_len, // NOTE the LENGTH field => 802.3 header!
818 NULL,
824 else // PVST+ => 802.3 with 802.1Q
826 t = libnet_build_802_1q(tx.eth_dst,
827 tx.eth_src,
828 0x8100,
829 priority,
830 0x00, // CFI
831 vlan,
832 0x32, //tx.eth_len,
833 NULL,
840 if (t == -1)
842 fprintf(stderr, " mz/send_bpdu: Can't build 802.3 header: %s\n",
843 libnet_geterror(l));
844 exit(EXIT_FAILURE);
848 // This is ugly but it works good ;-)
849 if (tx.count==0)
850 loop=1000000;
851 else
852 loop=tx.count;
854 // this is for the statistics:
855 mz_start = clock();
856 total_d = tx.count;
859 again:
861 for (i=1; i<=loop; i++)
863 if (!simulate) libnet_write(l);
865 if (verbose)
867 bs2str(root_id,dum1,8);
868 bs2str(bridge_id,dum2,8);
869 fprintf(stderr," sent BPDU: ");
870 fprintf(stderr,"%s ", (bpdumode==1) ? "conf" : "tcn ");
871 fprintf(stderr," id=%u ver=%u flags=%x rid=%s bid=%s\n"
872 " rpc=%u pid=%u age=%u maxage=%u hello=%u fwd_delay=%u\n",
873 id,
874 version,
875 flags,
876 dum1,
877 dum2,
878 root_pc,
879 port_id,
880 message_age,
881 max_age,
882 hello_time,
883 f_delay);
885 fprintf(stderr,"\n");
889 if (tx.delay) SLEEP (tx.delay);
892 if (tx.count==0)
894 goto again;
898 libnet_destroy(l);
900 return 0;