Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 94696 Details for
Bug 144526
arpping misses a signal for timeout causing latest /etc/init.d/net.* scripts to hang
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
new arping.c
arping.c (text/plain), 11.61 KB, created by
erik quanstrom
on 2006-08-20 07:21:05 UTC
(
hide
)
Description:
new arping.c
Filename:
MIME Type:
Creator:
erik quanstrom
Created:
2006-08-20 07:21:05 UTC
Size:
11.61 KB
patch
obsolete
>/* > * arping.c > * > * This program is free software; you can redistribute it and/or > * modify it under the terms of the GNU General Public License > * as published by the Free Software Foundation; either version > * 2 of the License, or (at your option) any later version. > * > * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> > * 2006.08.18 erik quanstrom <quanstro@quanstro.net> > * use select instead of signals so timeouts will work. > * > */ > >#include <stdlib.h> >#include <sys/param.h> >#include <sys/socket.h> >#include <linux/sockios.h> >#include <sys/file.h> >#include <sys/time.h> >#include <sys/ioctl.h> >#include <linux/if.h> >#include <linux/if_arp.h> >#include <sys/uio.h> > >#include <netdb.h> >#include <unistd.h> >#include <stdio.h> >#include <ctype.h> >#include <errno.h> >#include <string.h> >#include <netinet/in.h> >#include <arpa/inet.h> >#include <stdarg.h> > >#include "SNAPSHOT.h" > >static void usage(void) __attribute__((noreturn)); > >char *device="eth0"; >int ifindex; >char *source; >struct in_addr src, dst; >char *target; >int dad, unsolicited, advert; >int quiet; >int count=-1; >int ntosend=-1; >int ntorecv=-1; >int timeout; >struct timeval timeouttv; >int unicasting; >int s; >int broadcast_only; > >struct sockaddr_ll me; >struct sockaddr_ll he; > >struct timeval start, last; > >int sent, brd_sent; >int received, brd_recv, req_recv; > >#define MS_TDIFF(tv1,tv2) ( ((tv1).tv_sec-(tv2).tv_sec)*1000 + \ > ((tv1).tv_usec-(tv2).tv_usec)/1000 ) > >#define pkttrace(...) /* fprintf(stderr, __VA_ARGS__) */ > >void >errexit(int err, const char* fmt, ...) >{ > va_list ap; > > va_start(ap, fmt); > vfprintf(stderr, fmt, ap); > va_end(ap); > exit(err); >} > >void usage(void) >{ > fprintf(stderr, > "Usage: arping [-fqbDUAV] [-c count] [-w timeout] [-I device] [-s source] destination\n" > " -f : quit on first reply\n" > " -q : be quiet\n" > " -b : keep broadcasting, don't go unicast\n" > " -D : duplicate address detection mode\n" > " -U : Unsolicited ARP mode, update your neighbours\n" > " -A : ARP answer mode, update your neighbours\n" > " -V : print version and exit\n" > " -c count : how many packets to send\n" > " -w timeout : how long to wait for a reply\n" > " -I device : which ethernet device to use (eth0)\n" > " -s source : source ip address\n" > " destination : ask for what ip address\n" > ); > exit(2); >} > >int send_pack(int s, struct in_addr src, struct in_addr dst, > struct sockaddr_ll *ME, struct sockaddr_ll *HE) >{ > int err; > struct timeval now; > unsigned char buf[256]; > struct arphdr *ah = (struct arphdr*)buf; > unsigned char *p = (unsigned char *)(ah+1); > > ah->ar_hrd = htons(ME->sll_hatype); > if (ah->ar_hrd == htons(ARPHRD_FDDI)) > ah->ar_hrd = htons(ARPHRD_ETHER); > ah->ar_pro = htons(ETH_P_IP); > ah->ar_hln = ME->sll_halen; > ah->ar_pln = 4; > ah->ar_op = advert ? htons(ARPOP_REPLY) : htons(ARPOP_REQUEST); > > memcpy(p, &ME->sll_addr, ah->ar_hln); > p+=ME->sll_halen; > > memcpy(p, &src, 4); > p+=4; > > if (advert) > memcpy(p, &ME->sll_addr, ah->ar_hln); > else > memcpy(p, &HE->sll_addr, ah->ar_hln); > p+=ah->ar_hln; > > memcpy(p, &dst, 4); > p+=4; > > gettimeofday(&now, NULL); > pkttrace("sendto->\n"); > err = sendto(s, buf, p-buf, 0, (struct sockaddr*)HE, sizeof(*HE)); > pkttrace("sendto<-\n"); > if (err == p-buf) { > last = now; > sent++; > if (!unicasting) > brd_sent++; > } > return err; >} > >void finish(void) >{ > if (!quiet) { > fflush(stdout); > fprintf(stderr, "Sent %d probes (%d broadcast(s))\n", sent, brd_sent); > fprintf(stderr, "Received %d response(s)", received); > if (brd_recv || req_recv) { > fprintf(stderr, " ("); > if (req_recv) > fprintf(stderr, "%d request(s)", req_recv); > if (brd_recv) > fprintf(stderr, "%s%d broadcast(s)", > req_recv ? ", " : "", > brd_recv); > fprintf(stderr, ")"); > } > fprintf(stderr, "\n"); > } > if (dad) > exit(!!received); > if (unsolicited) > exit(0); > exit(!received); >} > >void print_hex(unsigned char *p, int len) >{ > int i; > for (i=0; i<len-1; i++) > printf(":"); > if(len) > printf("%02X", p[i]); >} > >int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM) >{ > struct timeval tv; > struct arphdr *ah = (struct arphdr*)buf; > unsigned char *p = (unsigned char *)(ah+1); > struct in_addr src_ip, dst_ip; > > gettimeofday(&tv, NULL); > > /* Filter out wild packets */ > if (FROM->sll_pkttype != PACKET_HOST && > FROM->sll_pkttype != PACKET_BROADCAST && > FROM->sll_pkttype != PACKET_MULTICAST) > return 0; > > /* Only these types are recognised */ > if (ah->ar_op != htons(ARPOP_REQUEST) && > ah->ar_op != htons(ARPOP_REPLY)) > return 0; > > /* ARPHRD check and this darned FDDI hack here :-( */ > if (ah->ar_hrd != htons(FROM->sll_hatype) && > (FROM->sll_hatype != ARPHRD_FDDI || ah->ar_hrd != htons(ARPHRD_ETHER))) > return 0; > > /* Protocol must be IP. */ > if (ah->ar_pro != htons(ETH_P_IP)) > return 0; > if (ah->ar_pln != 4) > return 0; > if (ah->ar_hln != me.sll_halen) > return 0; > if (len < sizeof(*ah) + 2*(4 + ah->ar_hln)) > return 0; > memcpy(&src_ip, p+ah->ar_hln, 4); > memcpy(&dst_ip, p+ah->ar_hln+4+ah->ar_hln, 4); > if (!dad) { > if (src_ip.s_addr != dst.s_addr) > return 0; > if (src.s_addr != dst_ip.s_addr) > return 0; > if (memcmp(p+ah->ar_hln+4, &me.sll_addr, ah->ar_hln)) > return 0; > } else { > /* DAD packet was: > src_ip = 0 (or some src) > src_hw = ME > dst_ip = tested address > dst_hw = <unspec> > > We fail, if receive request/reply with: > src_ip = tested_address > src_hw != ME > if src_ip in request was not zero, check > also that it matches to dst_ip, otherwise > dst_ip/dst_hw do not matter. > */ > if (src_ip.s_addr != dst.s_addr) > return 0; > if (memcmp(p, &me.sll_addr, me.sll_halen) == 0) > return 0; > if (src.s_addr && src.s_addr != dst_ip.s_addr) > return 0; > } > if (!quiet) { > int s_printed = 0; > printf("%s ", FROM->sll_pkttype==PACKET_HOST ? "Unicast" : "Broadcast"); > printf("%s from ", ah->ar_op == htons(ARPOP_REPLY) ? "reply" : "request"); > printf("%s [", inet_ntoa(src_ip)); > print_hex(p, ah->ar_hln); > printf("] "); > if (dst_ip.s_addr != src.s_addr) { > printf("for %s ", inet_ntoa(dst_ip)); > s_printed = 1; > } > if (memcmp(p+ah->ar_hln+4, me.sll_addr, ah->ar_hln)) { > if (!s_printed) > printf("for "); > printf("["); > print_hex(p+ah->ar_hln+4, ah->ar_hln); > printf("]"); > } > if (last.tv_sec) { > long usecs = (tv.tv_sec-last.tv_sec) * 1000000 + > tv.tv_usec-last.tv_usec; > long msecs = (usecs+500)/1000; > usecs -= msecs*1000 - 500; > printf(" %ld.%03ldms\n", msecs, usecs); > } else { > printf(" UNSOLICITED?\n"); > } > fflush(stdout); > } > received++; > if (FROM->sll_pkttype != PACKET_HOST) > brd_recv++; > if (ah->ar_op == htons(ARPOP_REQUEST)) > req_recv++; > if(!broadcast_only) { > memcpy(he.sll_addr, p, me.sll_halen); > unicasting=1; > } > return 1; >} > > >unsigned char packet[4096]; // too big for stack on some arch. > >void >pktloop(void) >{ > struct sockaddr_ll from; > socklen_t alen = sizeof(from); > fd_set rset; > struct timeval tmo; > int cc, i; > > for(;;){ > if(ntosend-- == 0) > break; > send_pack(s, src, dst, &me, &he); > > gettimeofday(&tmo, 0); > if(timeout) > i = MS_TDIFF(timeouttv, tmo) ; > else > i = 1000; > if(i < 0) > break; > if(i > 1000) > i = 1000; // maximum select 1s. > tmo.tv_sec = i/1000; > tmo.tv_usec = (i%1000)*1000; > > FD_ZERO(&rset); > FD_SET(s, &rset); > pkttrace("select %d ; %d\n", (int)tmo.tv_sec, (int)tmo.tv_usec); > i = select(s+1, &rset, 0, 0, &tmo); > pkttrace("<- select\n"); > if(i == -1){ > perror("arping: select"); > exit(1); > } > if(i == 0){ > gettimeofday(&tmo, 0); > i = MS_TDIFF(timeouttv, tmo); > if(timeout && i <= 0) > break; > continue; > } > if ((cc = recvfrom(s, packet, sizeof(packet), 0, > (struct sockaddr *)&from, &alen)) < 0) { > perror("arping: recvfrom"); > continue; > } > if(recv_pack(packet, cc, &from)) > if(--ntorecv == 0) > break; > } >} > >int >main(int argc, char **argv) >{ > int ch, onereply; > > while ((ch = getopt(argc, argv, "h?bfDUAqc:w:s:I:V")) != EOF) { > switch(ch) { > case 'b': > broadcast_only = 1; > break; > case 'D': > dad++; > onereply = 1; > break; > case 'U': > unsolicited++; > break; > case 'A': > advert++; > unsolicited++; > break; > case 'q': > quiet++; > break; > case 'c': > count = atoi(optarg); > break; > case 'w': > gettimeofday(&timeouttv, 0); > timeouttv.tv_sec += atoi(optarg); > timeout = 1; > break; > case 'I': > device = optarg; > break; > case 'f': > onereply = 1; > break; > case 's': > source = optarg; > break; > case 'V': > printf("arping utility, iputils-ss%s\n", SNAPSHOT); > exit(0); > case 'h': > case '?': > default: > usage(); > } > } > argc -= optind; > argv += optind; > > if (argc != 1) > usage(); > target = *argv; > > if(onereply) > ntorecv = 1; > if(timeout) // strange ping compatability. > ntorecv = count; > else > ntosend = count; > > if (device == 0) { > fprintf(stderr, "arping: device (option -I) is required\n"); > usage(); > } > > s = socket(PF_PACKET, SOCK_DGRAM, 0); > if (s < 0) { > perror("arping: socket"); > exit(2); > } > setuid(getuid()); > > if (1) { > struct ifreq ifr; > memset(&ifr, 0, sizeof(ifr)); > strncpy(ifr.ifr_name, device, IFNAMSIZ-1); > if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) { > fprintf(stderr, "arping: unknown iface %s\n", device); > exit(2); > } > ifindex = ifr.ifr_ifindex; > > if (ioctl(s, SIOCGIFFLAGS, (char*)&ifr)) { > perror("arping: ioctl(SIOCGIFFLAGS)"); > exit(2); > } > if (!(ifr.ifr_flags&IFF_UP)) > errexit(2, "Interface \"%s\" is down\n", device); > if (ifr.ifr_flags&(IFF_NOARP|IFF_LOOPBACK)) > errexit(dad ? 0 : 2, "Interface \"%s\" is not ARPable\n", device); > } > > if (inet_aton(target, &dst) != 1) { > struct hostent *hp; > hp = gethostbyname2(target, AF_INET); > if (!hp) { > fprintf(stderr, "arping: unknown host %s\n", target); > exit(2); > } > memcpy(&dst, hp->h_addr, 4); > } > > if (source && inet_aton(source, &src) != 1) { > fprintf(stderr, "arping: invalid source %s\n", source); > exit(2); > } > > if (!dad && unsolicited && src.s_addr == 0) > src = dst; > > if (!dad || src.s_addr) { > struct sockaddr_in saddr; > int probe_fd = socket(AF_INET, SOCK_DGRAM, 0); > > if (probe_fd < 0) { > perror("arping: socket"); > exit(2); > } > if (device) { > if (setsockopt(probe_fd, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device)+1) == -1) > perror("WARNING: interface is ignored"); > } > memset(&saddr, 0, sizeof(saddr)); > saddr.sin_family = AF_INET; > if (src.s_addr) { > saddr.sin_addr = src; > if (bind(probe_fd, (struct sockaddr*)&saddr, sizeof(saddr)) == -1) { > perror("arping: bind"); > exit(2); > } > } else if (!dad) { > int on = 1; > socklen_t alen = sizeof(saddr); > > saddr.sin_port = htons(1025); > saddr.sin_addr = dst; > > if (setsockopt(probe_fd, SOL_SOCKET, SO_DONTROUTE, (char*)&on, sizeof(on)) == -1) > perror("WARNING: setsockopt(SO_DONTROUTE)"); > if (connect(probe_fd, (struct sockaddr*)&saddr, sizeof(saddr)) == -1) { > perror("arping: connect"); > exit(2); > } > if (getsockname(probe_fd, (struct sockaddr*)&saddr, &alen) == -1) { > perror("arping: getsockname"); > exit(2); > } > src = saddr.sin_addr; > } > close(probe_fd); > }; > > me.sll_family = AF_PACKET; > me.sll_ifindex = ifindex; > me.sll_protocol = htons(ETH_P_ARP); > if (bind(s, (struct sockaddr*)&me, sizeof(me)) == -1) { > perror("arping: bind"); > exit(2); > } > > if (1) { > socklen_t alen = sizeof(me); > if (getsockname(s, (struct sockaddr*)&me, &alen) == -1) { > perror("arping: getsockname"); > exit(2); > } > } > if (me.sll_halen == 0) > errexit(dad ? 0 : 2, "Interface \"%s\" is not ARPable (no ll address)\n", device); > > he = me; > memset(he.sll_addr, -1, he.sll_halen); > > if (!quiet) { > fprintf(stderr, "ARPING %s ", inet_ntoa(dst)); > fprintf(stderr, "from %s %s\n", inet_ntoa(src), device ? : ""); > } > > if (!src.s_addr && !dad) > errexit(2, "arping: no source address in not-DAD mode\n"); > > pktloop(); > finish(); > return 1; // shut up gcc. >} > >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 144526
:
94696
|
94734