1313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* 2313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * arping.c 3313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 4313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * This program is free software; you can redistribute it and/or 5313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * modify it under the terms of the GNU General Public License 6313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * as published by the Free Software Foundation; either version 7313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 2 of the License, or (at your option) any later version. 8313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 9313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> 10313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> 11313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */ 12313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 13313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <stdlib.h> 14313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <sys/param.h> 15313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <sys/socket.h> 16313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <linux/sockios.h> 17313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <sys/file.h> 18313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <sys/time.h> 19313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <sys/signal.h> 20313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <sys/ioctl.h> 21313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <net/if.h> 22313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <linux/if_packet.h> 23313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <linux/if_ether.h> 24313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <net/if_arp.h> 25313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <sys/uio.h> 26313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef CAPABILITIES 27313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <sys/prctl.h> 28313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <sys/capability.h> 29313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 30313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 31313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <netdb.h> 32313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <unistd.h> 33313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <stdio.h> 34313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <ctype.h> 35313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <errno.h> 36313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <string.h> 37313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <netinet/in.h> 38313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <arpa/inet.h> 39313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 40313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef USE_SYSFS 41313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <sysfs/libsysfs.h> 42313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistruct sysfs_devattr_values; 43313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 44313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 45313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifndef WITHOUT_IFADDRS 46313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <ifaddrs.h> 47313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 48313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 49313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef USE_IDN 50313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <idna.h> 51313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <locale.h> 52313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 53313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 54313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include "SNAPSHOT.h" 55313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 56313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void usage(void) __attribute__((noreturn)); 57313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 58313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef DEFAULT_DEVICE 59313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# define DEFAULT_DEVICE_STR DEFAULT_DEVICE 60313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#else 61313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# define DEFAULT_DEVICE NULL 62313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 63313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 64313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistruct device { 65313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti char *name; 66313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int ifindex; 67313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifndef WITHOUT_IFADDRS 68313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct ifaddrs *ifa; 69313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 70313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef USE_SYSFS 71313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct sysfs_devattr_values *sysfs; 72313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 73313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}; 74313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 75313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint quit_on_reply=0; 76313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistruct device device = { 77313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti .name = DEFAULT_DEVICE, 78313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}; 79313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittichar *source; 80313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistruct in_addr src, dst; 81313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittichar *target; 82313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint dad, unsolicited, advert; 83313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint quiet; 84313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint count=-1; 85313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint timeout; 86313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint unicasting; 87313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint s; 88313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint broadcast_only; 89313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 90313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistruct sockaddr_storage me; 91313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistruct sockaddr_storage he; 92313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 93313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistruct timeval start, last; 94313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 95313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint sent, brd_sent; 96313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint received, brd_recv, req_recv; 97313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 98313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifndef CAPABILITIES 99313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic uid_t euid; 100313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 101313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 102313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#define MS_TDIFF(tv1,tv2) ( ((tv1).tv_sec-(tv2).tv_sec)*1000 + \ 103313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ((tv1).tv_usec-(tv2).tv_usec)/1000 ) 104313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 105313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#define OFFSET_OF(name,ele) ((size_t)(((name *)0)->ele)) 106313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 107313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic inline socklen_t sll_len(size_t halen) 108313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 109313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti socklen_t len = OFFSET_OF(struct sockaddr_ll, sll_addr) + halen; 110313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (len < sizeof(struct sockaddr_ll)) 111313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti len = sizeof(struct sockaddr_ll); 112313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return len; 113313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 114313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 115313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#define SLL_LEN(hln) sll_len(hln) 116313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 117313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid usage(void) 118313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 119313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti fprintf(stderr, 120313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti "Usage: arping [-fqbDUAV] [-c count] [-w timeout] [-I device] [-s source] destination\n" 121313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti " -f : quit on first reply\n" 122313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti " -q : be quiet\n" 123313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti " -b : keep broadcasting, don't go unicast\n" 124313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti " -D : duplicate address detection mode\n" 125313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti " -U : Unsolicited ARP mode, update your neighbours\n" 126313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti " -A : ARP answer mode, update your neighbours\n" 127313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti " -V : print version and exit\n" 128313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti " -c count : how many packets to send\n" 129313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti " -w timeout : how long to wait for a reply\n" 130313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti " -I device : which ethernet device to use" 131313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef DEFAULT_DEVICE_STR 132313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti " (" DEFAULT_DEVICE_STR ")" 133313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 134313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti "\n" 135313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti " -s source : source ip address\n" 136313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti " destination : ask for what ip address\n" 137313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ); 138313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(2); 139313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 140313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 141313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid set_signal(int signo, void (*handler)(void)) 142313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 143313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct sigaction sa; 144313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 145313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti memset(&sa, 0, sizeof(sa)); 146313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sa.sa_handler = (void (*)(int))handler; 147313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sa.sa_flags = SA_RESTART; 148313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sigaction(signo, &sa, NULL); 149313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 150313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 151313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef CAPABILITIES 152313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic const cap_value_t caps[] = { CAP_NET_RAW, }; 153313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic cap_flag_value_t cap_raw = CAP_CLEAR; 154313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 155313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 156313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid limit_capabilities(void) 157313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 158313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef CAPABILITIES 159313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cap_t cap_p; 160313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 161313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cap_p = cap_get_proc(); 162313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!cap_p) { 163313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("arping: cap_get_proc"); 164313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(-1); 165313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 166313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 167313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cap_get_flag(cap_p, CAP_NET_RAW, CAP_PERMITTED, &cap_raw); 168313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 169313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (cap_raw != CAP_CLEAR) { 170313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (cap_clear(cap_p) < 0) { 171313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("arping: cap_clear"); 172313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(-1); 173313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 174313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 175313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cap_set_flag(cap_p, CAP_PERMITTED, 1, caps, CAP_SET); 176313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 177313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (cap_set_proc(cap_p) < 0) { 178313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("arping: cap_set_proc"); 179313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (errno != EPERM) 180313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(-1); 181313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 182313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 183313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 184313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (prctl(PR_SET_KEEPCAPS, 1) < 0) { 185313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("arping: prctl"); 186313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(-1); 187313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 188313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 189313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (setuid(getuid()) < 0) { 190313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("arping: setuid"); 191313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(-1); 192313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 193313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 194313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (prctl(PR_SET_KEEPCAPS, 0) < 0) { 195313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("arping: prctl"); 196313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(-1); 197313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 198313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 199313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cap_free(cap_p); 200313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#else 201313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti euid = geteuid(); 202313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 203313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 204313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 205313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint modify_capability_raw(int on) 206313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 207313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef CAPABILITIES 208313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cap_t cap_p; 209313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 210313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (cap_raw != CAP_SET) 211313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return on ? -1 : 0; 212313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 213313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cap_p = cap_get_proc(); 214313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!cap_p) { 215313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("arping: cap_get_proc"); 216313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return -1; 217313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 218313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 219313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cap_set_flag(cap_p, CAP_EFFECTIVE, 1, caps, on ? CAP_SET : CAP_CLEAR); 220313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 221313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (cap_set_proc(cap_p) < 0) { 222313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("arping: cap_set_proc"); 223313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return -1; 224313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 225313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 226313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cap_free(cap_p); 227313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#else 228313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (setuid(on ? euid : getuid())) { 229313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("arping: setuid"); 230313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return -1; 231313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 232313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 233313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return 0; 234313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 235313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 236313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic inline int enable_capability_raw(void) 237313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 238313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return modify_capability_raw(1); 239313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 240313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 241313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic inline int disable_capability_raw(void) 242313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 243313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return modify_capability_raw(0); 244313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 245313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 246313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid drop_capabilities(void) 247313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 248313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef CAPABILITIES 249313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cap_t cap_p = cap_init(); 250313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 251313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!cap_p) { 252313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("arping: cap_init"); 253313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(-1); 254313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 255313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 256313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (cap_set_proc(cap_p) < 0) { 257313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("arping: cap_set_proc"); 258313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(-1); 259313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 260313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 261313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cap_free(cap_p); 262313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#else 263313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (setuid(getuid()) < 0) { 264313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("arping: setuid"); 265313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(-1); 266313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 267313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 268313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 269313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 270313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint send_pack(int s, struct in_addr src, struct in_addr dst, 271313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct sockaddr_ll *ME, struct sockaddr_ll *HE) 272313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 273313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int err; 274313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct timeval now; 275313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti unsigned char buf[256]; 276313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct arphdr *ah = (struct arphdr*)buf; 277313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti unsigned char *p = (unsigned char *)(ah+1); 278313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 279313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ah->ar_hrd = htons(ME->sll_hatype); 280313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ah->ar_hrd == htons(ARPHRD_FDDI)) 281313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ah->ar_hrd = htons(ARPHRD_ETHER); 282313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ah->ar_pro = htons(ETH_P_IP); 283313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ah->ar_hln = ME->sll_halen; 284313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ah->ar_pln = 4; 285313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ah->ar_op = advert ? htons(ARPOP_REPLY) : htons(ARPOP_REQUEST); 286313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 287313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti memcpy(p, &ME->sll_addr, ah->ar_hln); 288313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti p+=ME->sll_halen; 289313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 290313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti memcpy(p, &src, 4); 291313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti p+=4; 292313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 293313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (advert) 294313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti memcpy(p, &ME->sll_addr, ah->ar_hln); 295313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti else 296313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti memcpy(p, &HE->sll_addr, ah->ar_hln); 297313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti p+=ah->ar_hln; 298313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 299313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti memcpy(p, &dst, 4); 300313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti p+=4; 301313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 302313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti gettimeofday(&now, NULL); 303313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti err = sendto(s, buf, p-buf, 0, (struct sockaddr*)HE, SLL_LEN(ah->ar_hln)); 304313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (err == p-buf) { 305313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti last = now; 306313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sent++; 307313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!unicasting) 308313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti brd_sent++; 309313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 310313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return err; 311313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 312313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 313313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid finish(void) 314313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 315313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!quiet) { 316313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf("Sent %d probes (%d broadcast(s))\n", sent, brd_sent); 317313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf("Received %d response(s)", received); 318313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (brd_recv || req_recv) { 319313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf(" ("); 320313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (req_recv) 321313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf("%d request(s)", req_recv); 322313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (brd_recv) 323313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf("%s%d broadcast(s)", 324313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti req_recv ? ", " : "", 325313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti brd_recv); 326313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf(")"); 327313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 328313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf("\n"); 329313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti fflush(stdout); 330313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 331313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (dad) 332313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(!!received); 333313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (unsolicited) 334313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(0); 335313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(!received); 336313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 337313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 338313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid catcher(void) 339313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 340313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct timeval tv, tv_s, tv_o; 341313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 342313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti gettimeofday(&tv, NULL); 343313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 344313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (start.tv_sec==0) 345313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti start = tv; 346313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 347313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti timersub(&tv, &start, &tv_s); 348313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tv_o.tv_sec = timeout; 349313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tv_o.tv_usec = 500 * 1000; 350313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 351313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (count-- == 0 || (timeout && timercmp(&tv_s, &tv_o, >))) 352313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti finish(); 353313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 354313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti timersub(&tv, &last, &tv_s); 355313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tv_o.tv_sec = 0; 356313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 357313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (last.tv_sec==0 || timercmp(&tv_s, &tv_o, >)) { 358313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti send_pack(s, src, dst, 359313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (struct sockaddr_ll *)&me, (struct sockaddr_ll *)&he); 360313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (count == 0 && unsolicited) 361313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti finish(); 362313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 363313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti alarm(1); 364313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 365313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 366313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid print_hex(unsigned char *p, int len) 367313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 368313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int i; 369313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti for (i=0; i<len; i++) { 370313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf("%02X", p[i]); 371313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (i != len-1) 372313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf(":"); 373313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 374313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 375313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 376313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM) 377313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 378313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct timeval tv; 379313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct arphdr *ah = (struct arphdr*)buf; 380313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti unsigned char *p = (unsigned char *)(ah+1); 381313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct in_addr src_ip, dst_ip; 382313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 383313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti gettimeofday(&tv, NULL); 384313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 385313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* Filter out wild packets */ 386313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (FROM->sll_pkttype != PACKET_HOST && 387313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti FROM->sll_pkttype != PACKET_BROADCAST && 388313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti FROM->sll_pkttype != PACKET_MULTICAST) 389313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return 0; 390313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 391313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* Only these types are recognised */ 392313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ah->ar_op != htons(ARPOP_REQUEST) && 393313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ah->ar_op != htons(ARPOP_REPLY)) 394313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return 0; 395313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 396313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* ARPHRD check and this darned FDDI hack here :-( */ 397313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ah->ar_hrd != htons(FROM->sll_hatype) && 398313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (FROM->sll_hatype != ARPHRD_FDDI || ah->ar_hrd != htons(ARPHRD_ETHER))) 399313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return 0; 400313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 401313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* Protocol must be IP. */ 402313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ah->ar_pro != htons(ETH_P_IP)) 403313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return 0; 404313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ah->ar_pln != 4) 405313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return 0; 406313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ah->ar_hln != ((struct sockaddr_ll *)&me)->sll_halen) 407313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return 0; 408313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (len < sizeof(*ah) + 2*(4 + ah->ar_hln)) 409313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return 0; 410313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti memcpy(&src_ip, p+ah->ar_hln, 4); 411313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti memcpy(&dst_ip, p+ah->ar_hln+4+ah->ar_hln, 4); 412313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!dad) { 413313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (src_ip.s_addr != dst.s_addr) 414313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return 0; 415313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (src.s_addr != dst_ip.s_addr) 416313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return 0; 417313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (memcmp(p+ah->ar_hln+4, ((struct sockaddr_ll *)&me)->sll_addr, ah->ar_hln)) 418313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return 0; 419313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } else { 420313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* DAD packet was: 421313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti src_ip = 0 (or some src) 422313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti src_hw = ME 423313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti dst_ip = tested address 424313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti dst_hw = <unspec> 425313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 426313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti We fail, if receive request/reply with: 427313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti src_ip = tested_address 428313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti src_hw != ME 429313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if src_ip in request was not zero, check 430313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti also that it matches to dst_ip, otherwise 431313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti dst_ip/dst_hw do not matter. 432313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */ 433313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (src_ip.s_addr != dst.s_addr) 434313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return 0; 435313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (memcmp(p, ((struct sockaddr_ll *)&me)->sll_addr, ((struct sockaddr_ll *)&me)->sll_halen) == 0) 436313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return 0; 437313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (src.s_addr && src.s_addr != dst_ip.s_addr) 438313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return 0; 439313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 440313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!quiet) { 441313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int s_printed = 0; 442313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf("%s ", FROM->sll_pkttype==PACKET_HOST ? "Unicast" : "Broadcast"); 443313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf("%s from ", ah->ar_op == htons(ARPOP_REPLY) ? "reply" : "request"); 444313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf("%s [", inet_ntoa(src_ip)); 445313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti print_hex(p, ah->ar_hln); 446313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf("] "); 447313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (dst_ip.s_addr != src.s_addr) { 448313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf("for %s ", inet_ntoa(dst_ip)); 449313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti s_printed = 1; 450313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 451313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (memcmp(p+ah->ar_hln+4, ((struct sockaddr_ll *)&me)->sll_addr, ah->ar_hln)) { 452313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!s_printed) 453313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf("for "); 454313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf("["); 455313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti print_hex(p+ah->ar_hln+4, ah->ar_hln); 456313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf("]"); 457313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 458313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (last.tv_sec) { 459313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti long usecs = (tv.tv_sec-last.tv_sec) * 1000000 + 460313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tv.tv_usec-last.tv_usec; 461313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti long msecs = (usecs+500)/1000; 462313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti usecs -= msecs*1000 - 500; 463313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf(" %ld.%03ldms\n", msecs, usecs); 464313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } else { 465313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf(" UNSOLICITED?\n"); 466313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 467313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti fflush(stdout); 468313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 469313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti received++; 470313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (FROM->sll_pkttype != PACKET_HOST) 471313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti brd_recv++; 472313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ah->ar_op == htons(ARPOP_REQUEST)) 473313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti req_recv++; 474313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (quit_on_reply) 475313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti finish(); 476313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if(!broadcast_only) { 477313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti memcpy(((struct sockaddr_ll *)&he)->sll_addr, p, ((struct sockaddr_ll *)&me)->sll_halen); 478313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti unicasting=1; 479313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 480313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return 1; 481313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 482313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 483313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef USE_SYSFS 484313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiunion sysfs_devattr_value { 485313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti unsigned long ulong; 486313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti void *ptr; 487313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}; 488313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 489313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittienum { 490313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti SYSFS_DEVATTR_IFINDEX, 491313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti SYSFS_DEVATTR_FLAGS, 492313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti SYSFS_DEVATTR_ADDR_LEN, 493313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if 0 494313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti SYSFS_DEVATTR_TYPE, 495313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti SYSFS_DEVATTR_ADDRESS, 496313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 497313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti SYSFS_DEVATTR_BROADCAST, 498313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti SYSFS_DEVATTR_NUM 499313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}; 500313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 501313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistruct sysfs_devattr_values 502313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 503313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti char *ifname; 504313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti union sysfs_devattr_value value[SYSFS_DEVATTR_NUM]; 505313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}; 506313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 507313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int sysfs_devattr_ulong_dec(char *ptr, struct sysfs_devattr_values *v, unsigned idx); 508313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int sysfs_devattr_ulong_hex(char *ptr, struct sysfs_devattr_values *v, unsigned idx); 509313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int sysfs_devattr_macaddr(char *ptr, struct sysfs_devattr_values *v, unsigned idx); 510313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 511313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistruct sysfs_devattrs { 512313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti const char *name; 513313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int (*handler)(char *ptr, struct sysfs_devattr_values *v, unsigned int idx); 514313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int free; 515313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} sysfs_devattrs[SYSFS_DEVATTR_NUM] = { 516313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti [SYSFS_DEVATTR_IFINDEX] = { 517313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti .name = "ifindex", 518313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti .handler = sysfs_devattr_ulong_dec, 519313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti }, 520313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti [SYSFS_DEVATTR_ADDR_LEN] = { 521313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti .name = "addr_len", 522313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti .handler = sysfs_devattr_ulong_dec, 523313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti }, 524313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti [SYSFS_DEVATTR_FLAGS] = { 525313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti .name = "flags", 526313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti .handler = sysfs_devattr_ulong_hex, 527313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti }, 528313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if 0 529313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti [SYSFS_DEVATTR_TYPE] = { 530313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti .name = "type", 531313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti .handler = sysfs_devattr_ulong_dec, 532313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti }, 533313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti [SYSFS_DEVATTR_ADDRESS] = { 534313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti .name = "address", 535313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti .handler = sysfs_devattr_macaddr, 536313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti .free = 1, 537313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti }, 538313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 539313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti [SYSFS_DEVATTR_BROADCAST] = { 540313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti .name = "broadcast", 541313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti .handler = sysfs_devattr_macaddr, 542313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti .free = 1, 543313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti }, 544313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}; 545313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 546313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 547313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* 548313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * find_device() 549313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 550313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * This function checks 1) if the device (if given) is okay for ARP, 551313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * or 2) find fist appropriate device on the system. 552313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 553313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Return value: 554313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * >0 : Succeeded, and appropriate device not found. 555313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * device.ifindex remains 0. 556313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 0 : Succeeded, and approptiate device found. 557313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * device.ifindex is set. 558313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * <0 : Failed. Support not found, or other 559313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * : system error. Try other method. 560313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 561313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * If an appropriate device found, it is recorded inside the 562313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * "device" variable for later reference. 563313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 564313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * We have several implementations for this. 565313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * by_ifaddrs(): requires getifaddr() in glibc, and rtnetlink in 566313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * kernel. default and recommended for recent systems. 567313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * by_sysfs(): requires libsysfs , and sysfs in kernel. 568313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * by_ioctl(): unable to list devices without ipv4 address; this 569313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * means, you need to supply the device name for 570313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * DAD purpose. 571313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */ 572313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* Common check for ifa->ifa_flags */ 573313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int check_ifflags(unsigned int ifflags, int fatal) 574313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 575313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!(ifflags & IFF_UP)) { 576313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (fatal) { 577313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!quiet) 578313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf("Interface \"%s\" is down\n", device.name); 579313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(2); 580313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 581313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return -1; 582313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 583313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ifflags & (IFF_NOARP | IFF_LOOPBACK)) { 584313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (fatal) { 585313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!quiet) 586313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf("Interface \"%s\" is not ARPable\n", device.name); 587313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(dad ? 0 : 2); 588313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 589313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return -1; 590313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 591313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return 0; 592313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 593313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 594313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int find_device_by_ifaddrs(void) 595313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 596313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifndef WITHOUT_IFADDRS 597313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int rc; 598313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct ifaddrs *ifa0, *ifa; 599313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int count = 0; 600313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 601313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti rc = getifaddrs(&ifa0); 602313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (rc) { 603313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("getifaddrs"); 604313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return -1; 605313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 606313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 607313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti for (ifa = ifa0; ifa; ifa = ifa->ifa_next) { 608313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!ifa->ifa_addr) 609313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti continue; 610313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ifa->ifa_addr->sa_family != AF_PACKET) 611313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti continue; 612313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (device.name && ifa->ifa_name && strcmp(ifa->ifa_name, device.name)) 613313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti continue; 614313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 615313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (check_ifflags(ifa->ifa_flags, device.name != NULL) < 0) 616313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti continue; 617313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 618313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!((struct sockaddr_ll *)ifa->ifa_addr)->sll_halen) 619313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti continue; 620313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!ifa->ifa_broadaddr) 621313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti continue; 622313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 623313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti device.ifa = ifa; 624313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 625313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (count++) 626313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 627313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 628313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 629313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (count == 1 && device.ifa) { 630313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti device.ifindex = if_nametoindex(device.ifa->ifa_name); 631313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!device.ifindex) { 632313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("arping: if_nametoindex"); 633313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti freeifaddrs(ifa0); 634313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return -1; 635313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 636313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti device.name = device.ifa->ifa_name; 637313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return 0; 638313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 639313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return 1; 640313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#else 641313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return -1; 642313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 643313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 644313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 645313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef USE_SYSFS 646313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void sysfs_devattr_values_init(struct sysfs_devattr_values *v, int do_free) 647313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 648313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int i; 649313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (do_free) { 650313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti free(v->ifname); 651313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti for (i = 0; i < SYSFS_DEVATTR_NUM; i++) { 652313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (sysfs_devattrs[i].free) 653313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti free(v->value[i].ptr); 654313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 655313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 656313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti memset(v, 0, sizeof(*v)); 657313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 658313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 659313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int sysfs_devattr_ulong(char *ptr, struct sysfs_devattr_values *v, unsigned int idx, 660313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti unsigned int base) 661313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 662313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti unsigned long *p; 663313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti char *ep; 664313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 665313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!ptr || !v) 666313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return -1; 667313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 668313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti p = &v->value[idx].ulong; 669313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti errno = 0; 670313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *p = strtoul(ptr, &ep, base); 671313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if ((*ptr && isspace(*ptr & 0xff)) || errno || (*ep != '\0' && *ep != '\n')) 672313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti goto out; 673313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 674313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return 0; 675313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiout: 676313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return -1; 677313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 678313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 679313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int sysfs_devattr_ulong_dec(char *ptr, struct sysfs_devattr_values *v, unsigned int idx) 680313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 681313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int rc = sysfs_devattr_ulong(ptr, v, idx, 10); 682313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return rc; 683313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 684313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 685313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int sysfs_devattr_ulong_hex(char *ptr, struct sysfs_devattr_values *v, unsigned int idx) 686313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 687313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int rc = sysfs_devattr_ulong(ptr, v, idx, 16); 688313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return rc; 689313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 690313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 691313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int sysfs_devattr_macaddr(char *ptr, struct sysfs_devattr_values *v, unsigned int idx) 692313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 693313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti unsigned char *m; 694313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int i; 695313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti unsigned int addrlen; 696313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 697313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!ptr || !v) 698313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return -1; 699313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 700313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti addrlen = v->value[SYSFS_DEVATTR_ADDR_LEN].ulong; 701313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti m = malloc(addrlen); 702313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 703313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti for (i = 0; i < addrlen; i++) { 704313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (i && *(ptr + i * 3 - 1) != ':') 705313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti goto out; 706313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (sscanf(ptr + i * 3, "%02hhx", &m[i]) != 1) 707313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti goto out; 708313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 709313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 710313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti v->value[idx].ptr = m; 711313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return 0; 712313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiout: 713313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti free(m); 714313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return -1; 715313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 716313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 717313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 718313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint find_device_by_sysfs(void) 719313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 720313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int rc = -1; 721313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef USE_SYSFS 722313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct sysfs_class *cls_net; 723313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct dlist *dev_list; 724313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct sysfs_class_device *dev; 725313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct sysfs_attribute *dev_attr; 726313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct sysfs_devattr_values sysfs_devattr_values; 727313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int count = 0; 728313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 729313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!device.sysfs) { 730313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti device.sysfs = malloc(sizeof(*device.sysfs)); 731313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sysfs_devattr_values_init(device.sysfs, 0); 732313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 733313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 734313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cls_net = sysfs_open_class("net"); 735313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!cls_net) { 736313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("sysfs_open_class"); 737313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return -1; 738313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 739313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 740313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti dev_list = sysfs_get_class_devices(cls_net); 741313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!dev_list) { 742313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("sysfs_get_class_devices"); 743313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti goto out; 744313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 745313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 746313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sysfs_devattr_values_init(&sysfs_devattr_values, 0); 747313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 748313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti dlist_for_each_data(dev_list, dev, struct sysfs_class_device) { 749313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int i; 750313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int rc = -1; 751313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 752313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (device.name && strcmp(dev->name, device.name)) 753313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti goto do_next; 754313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 755313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sysfs_devattr_values_init(&sysfs_devattr_values, 1); 756313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 757313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti for (i = 0; i < SYSFS_DEVATTR_NUM; i++) { 758313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 759313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti dev_attr = sysfs_get_classdev_attr(dev, sysfs_devattrs[i].name); 760313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!dev_attr) { 761313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("sysfs_get_classdev_attr"); 762313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti rc = -1; 763313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 764313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 765313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (sysfs_read_attribute(dev_attr)) { 766313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("sysfs_read_attribute"); 767313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti rc = -1; 768313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 769313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 770313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti rc = sysfs_devattrs[i].handler(dev_attr->value, &sysfs_devattr_values, i); 771313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 772313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (rc < 0) 773313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 774313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 775313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 776313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (rc < 0) 777313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti goto do_next; 778313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 779313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (check_ifflags(sysfs_devattr_values.value[SYSFS_DEVATTR_FLAGS].ulong, 780313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti device.name != NULL) < 0) 781313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti goto do_next; 782313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 783313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!sysfs_devattr_values.value[SYSFS_DEVATTR_ADDR_LEN].ulong) 784313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti goto do_next; 785313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 786313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (device.sysfs->value[SYSFS_DEVATTR_IFINDEX].ulong) { 787313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (device.sysfs->value[SYSFS_DEVATTR_FLAGS].ulong & IFF_RUNNING) 788313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti goto do_next; 789313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 790313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 791313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sysfs_devattr_values.ifname = strdup(dev->name); 792313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!sysfs_devattr_values.ifname) { 793313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("malloc"); 794313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti goto out; 795313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 796313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 797313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sysfs_devattr_values_init(device.sysfs, 1); 798313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti memcpy(device.sysfs, &sysfs_devattr_values, sizeof(*device.sysfs)); 799313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sysfs_devattr_values_init(&sysfs_devattr_values, 0); 800313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 801313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (count++) 802313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 803313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 804313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti continue; 805313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittido_next: 806313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sysfs_devattr_values_init(&sysfs_devattr_values, 1); 807313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 808313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 809313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (count == 1) { 810313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti device.ifindex = device.sysfs->value[SYSFS_DEVATTR_IFINDEX].ulong; 811313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti device.name = device.sysfs->ifname; 812313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 813313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti rc = !device.ifindex; 814313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiout: 815313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sysfs_close_class(cls_net); 816313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 817313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return rc; 818313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 819313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 820313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int check_device_by_ioctl(int s, struct ifreq *ifr) 821313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 822313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ioctl(s, SIOCGIFFLAGS, ifr) < 0) { 823313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("ioctl(SIOCGIFINDEX"); 824313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return -1; 825313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 826313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 827313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (check_ifflags(ifr->ifr_flags, device.name != NULL) < 0) 828313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return 1; 829313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 830313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ioctl(s, SIOCGIFINDEX, ifr) < 0) { 831313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("ioctl(SIOCGIFINDEX"); 832313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return -1; 833313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 834313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 835313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return 0; 836313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 837313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 838313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int find_device_by_ioctl(void) 839313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 840313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int s; 841313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct ifreq *ifr0, *ifr, *ifr_end; 842313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti size_t ifrsize = sizeof(*ifr); 843313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct ifconf ifc; 844313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti static struct ifreq ifrbuf; 845313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int count = 0; 846313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 847313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti s = socket(AF_INET, SOCK_DGRAM, 0); 848313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (s < 0) { 849313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("socket"); 850313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return -1; 851313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 852313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 853313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti memset(&ifrbuf, 0, sizeof(ifrbuf)); 854313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 855313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (device.name) { 856313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti strncpy(ifrbuf.ifr_name, device.name, sizeof(ifrbuf.ifr_name) - 1); 857313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (check_device_by_ioctl(s, &ifrbuf)) 858313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti goto out; 859313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti count++; 860313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } else { 861313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti do { 862313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int rc; 863313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifr0 = malloc(ifrsize); 864313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!ifr0) { 865313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("malloc"); 866313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti goto out; 867313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 868313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 869313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifc.ifc_buf = (char *)ifr0; 870313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifc.ifc_len = ifrsize; 871313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 872313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti rc = ioctl(s, SIOCGIFCONF, &ifc); 873313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (rc < 0) { 874313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("ioctl(SIOCFIFCONF"); 875313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti goto out; 876313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 877313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 878313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ifc.ifc_len + sizeof(*ifr0) + sizeof(struct sockaddr_storage) - sizeof(struct sockaddr) <= ifrsize) 879313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 880313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifrsize *= 2; 881313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti free(ifr0); 882313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifr0 = NULL; 883313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } while(ifrsize < INT_MAX / 2); 884313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 885313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!ifr0) { 886313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti fprintf(stderr, "arping: too many interfaces!?\n"); 887313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti goto out; 888313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 889313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 890313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifr_end = (struct ifreq *)(((char *)ifr0) + ifc.ifc_len - sizeof(*ifr0)); 891313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti for (ifr = ifr0; ifr <= ifr_end; ifr++) { 892313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (check_device_by_ioctl(s, &ifrbuf)) 893313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti continue; 894313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti memcpy(&ifrbuf.ifr_name, ifr->ifr_name, sizeof(ifrbuf.ifr_name)); 895313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (count++) 896313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 897313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 898313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 899313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 900313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti close(s); 901313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 902313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (count == 1) { 903313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti device.ifindex = ifrbuf.ifr_ifindex; 904313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti device.name = ifrbuf.ifr_name; 905313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 906313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return !device.ifindex; 907313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiout: 908313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti close(s); 909313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return -1; 910313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 911313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 912313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int find_device(void) 913313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 914313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int rc; 915313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti rc = find_device_by_ifaddrs(); 916313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (rc >= 0) 917313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti goto out; 918313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti rc = find_device_by_sysfs(); 919313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (rc >= 0) 920313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti goto out; 921313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti rc = find_device_by_ioctl(); 922313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiout: 923313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return rc; 924313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 925313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 926313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* 927313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * set_device_broadcast() 928313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 929313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * This fills the device "broadcast address" 930313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * based on information found by find_device() funcion. 931313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */ 932313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int set_device_broadcast_ifaddrs_one(struct device *device, unsigned char *ba, size_t balen, int fatal) 933313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 934313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifndef WITHOUT_IFADDRS 935313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct ifaddrs *ifa; 936313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct sockaddr_ll *sll; 937313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 938313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!device) 939313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return -1; 940313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 941313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifa = device->ifa; 942313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!ifa) 943313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return -1; 944313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 945313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sll = (struct sockaddr_ll *)ifa->ifa_broadaddr; 946313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 947313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (sll->sll_halen != balen) { 948313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (fatal) { 949313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!quiet) 950313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf("Address length does not match...\n"); 951313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(2); 952313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 953313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return -1; 954313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 955313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti memcpy(ba, sll->sll_addr, sll->sll_halen); 956313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return 0; 957313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#else 958313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return -1; 959313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 960313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 961313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint set_device_broadcast_sysfs(struct device *device, unsigned char *ba, size_t balen) 962313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 963313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef USE_SYSFS 964313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct sysfs_devattr_values *v; 965313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!device) 966313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return -1; 967313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti v = device->sysfs; 968313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!v) 969313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return -1; 970313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (v->value[SYSFS_DEVATTR_ADDR_LEN].ulong != balen) 971313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return -1; 972313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti memcpy(ba, v->value[SYSFS_DEVATTR_BROADCAST].ptr, balen); 973313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return 0; 974313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#else 975313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return -1; 976313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 977313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 978313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 979313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int set_device_broadcast_fallback(struct device *device, unsigned char *ba, size_t balen) 980313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 981313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!quiet) 982313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti fprintf(stderr, "WARNING: using default broadcast address.\n"); 983313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti memset(ba, -1, balen); 984313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return 0; 985313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 986313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 987313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void set_device_broadcast(struct device *dev, unsigned char *ba, size_t balen) 988313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 989313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!set_device_broadcast_ifaddrs_one(dev, ba, balen, 0)) 990313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return; 991313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!set_device_broadcast_sysfs(dev, ba, balen)) 992313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return; 993313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti set_device_broadcast_fallback(dev, ba, balen); 994313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 995313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 996313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint 997313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittimain(int argc, char **argv) 998313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 999313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int socket_errno; 1000313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int ch; 1001313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1002313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti limit_capabilities(); 1003313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1004313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef USE_IDN 1005313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti setlocale(LC_ALL, ""); 1006313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 1007313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1008313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti enable_capability_raw(); 1009313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1010313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti s = socket(PF_PACKET, SOCK_DGRAM, 0); 1011313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti socket_errno = errno; 1012313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1013313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti disable_capability_raw(); 1014313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1015313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti while ((ch = getopt(argc, argv, "h?bfDUAqc:w:s:I:V")) != EOF) { 1016313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti switch(ch) { 1017313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'b': 1018313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti broadcast_only=1; 1019313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 1020313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'D': 1021313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti dad++; 1022313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti quit_on_reply=1; 1023313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 1024313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'U': 1025313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti unsolicited++; 1026313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 1027313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'A': 1028313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti advert++; 1029313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti unsolicited++; 1030313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 1031313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'q': 1032313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti quiet++; 1033313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 1034313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'c': 1035313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti count = atoi(optarg); 1036313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 1037313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'w': 1038313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti timeout = atoi(optarg); 1039313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 1040313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'I': 1041313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti device.name = optarg; 1042313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 1043313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'f': 1044313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti quit_on_reply=1; 1045313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 1046313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 's': 1047313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti source = optarg; 1048313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 1049313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'V': 1050313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf("arping utility, iputils-%s\n", SNAPSHOT); 1051313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(0); 1052313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'h': 1053313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case '?': 1054313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti default: 1055313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti usage(); 1056313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1057313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1058313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti argc -= optind; 1059313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti argv += optind; 1060313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1061313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (argc != 1) 1062313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti usage(); 1063313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1064313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti target = *argv; 1065313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1066313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (device.name && !*device.name) 1067313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti device.name = NULL; 1068313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1069313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (s < 0) { 1070313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti errno = socket_errno; 1071313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("arping: socket"); 1072313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(2); 1073313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1074313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1075313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (find_device() < 0) 1076313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(2); 1077313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1078313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!device.ifindex) { 1079313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (device.name) { 1080313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti fprintf(stderr, "arping: Device %s not available.\n", device.name); 1081313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(2); 1082313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1083313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti fprintf(stderr, "arping: device (option -I) is required.\n"); 1084313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti usage(); 1085313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1086313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1087313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (inet_aton(target, &dst) != 1) { 1088313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct hostent *hp; 1089313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti char *idn = target; 1090313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef USE_IDN 1091313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int rc; 1092313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1093313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti rc = idna_to_ascii_lz(target, &idn, 0); 1094313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1095313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (rc != IDNA_SUCCESS) { 1096313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti fprintf(stderr, "arping: IDN encoding failed: %s\n", idna_strerror(rc)); 1097313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(2); 1098313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1099313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 1100313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1101313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti hp = gethostbyname2(idn, AF_INET); 1102313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!hp) { 1103313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti fprintf(stderr, "arping: unknown host %s\n", target); 1104313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(2); 1105313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1106313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1107313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef USE_IDN 1108313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti free(idn); 1109313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 1110313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1111313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti memcpy(&dst, hp->h_addr, 4); 1112313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1113313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1114313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (source && inet_aton(source, &src) != 1) { 1115313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti fprintf(stderr, "arping: invalid source %s\n", source); 1116313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(2); 1117313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1118313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1119313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!dad && unsolicited && src.s_addr == 0) 1120313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti src = dst; 1121313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1122313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!dad || src.s_addr) { 1123313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct sockaddr_in saddr; 1124313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int probe_fd = socket(AF_INET, SOCK_DGRAM, 0); 1125313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1126313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (probe_fd < 0) { 1127313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("socket"); 1128313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(2); 1129313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1130313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (device.name) { 1131313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti enable_capability_raw(); 1132313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1133313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (setsockopt(probe_fd, SOL_SOCKET, SO_BINDTODEVICE, device.name, strlen(device.name)+1) == -1) 1134313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("WARNING: interface is ignored"); 1135313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1136313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti disable_capability_raw(); 1137313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1138313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti memset(&saddr, 0, sizeof(saddr)); 1139313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti saddr.sin_family = AF_INET; 1140313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (src.s_addr) { 1141313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti saddr.sin_addr = src; 1142313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (bind(probe_fd, (struct sockaddr*)&saddr, sizeof(saddr)) == -1) { 1143313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("bind"); 1144313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(2); 1145313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1146313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } else if (!dad) { 1147313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int on = 1; 1148313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti socklen_t alen = sizeof(saddr); 1149313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1150313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti saddr.sin_port = htons(1025); 1151313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti saddr.sin_addr = dst; 1152313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1153313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (setsockopt(probe_fd, SOL_SOCKET, SO_DONTROUTE, (char*)&on, sizeof(on)) == -1) 1154313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("WARNING: setsockopt(SO_DONTROUTE)"); 1155313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (connect(probe_fd, (struct sockaddr*)&saddr, sizeof(saddr)) == -1) { 1156313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("connect"); 1157313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(2); 1158313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1159313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (getsockname(probe_fd, (struct sockaddr*)&saddr, &alen) == -1) { 1160313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("getsockname"); 1161313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(2); 1162313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1163313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti src = saddr.sin_addr; 1164313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1165313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti close(probe_fd); 1166313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti }; 1167313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1168313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ((struct sockaddr_ll *)&me)->sll_family = AF_PACKET; 1169313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ((struct sockaddr_ll *)&me)->sll_ifindex = device.ifindex; 1170313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ((struct sockaddr_ll *)&me)->sll_protocol = htons(ETH_P_ARP); 1171313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (bind(s, (struct sockaddr*)&me, sizeof(me)) == -1) { 1172313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("bind"); 1173313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(2); 1174313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1175313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1176313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (1) { 1177313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti socklen_t alen = sizeof(me); 1178313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (getsockname(s, (struct sockaddr*)&me, &alen) == -1) { 1179313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("getsockname"); 1180313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(2); 1181313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1182313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1183313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (((struct sockaddr_ll *)&me)->sll_halen == 0) { 1184313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!quiet) 1185313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf("Interface \"%s\" is not ARPable (no ll address)\n", device.name); 1186313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(dad?0:2); 1187313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1188313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1189313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti he = me; 1190313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1191313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti set_device_broadcast(&device, ((struct sockaddr_ll *)&he)->sll_addr, 1192313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ((struct sockaddr_ll *)&he)->sll_halen); 1193313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1194313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!quiet) { 1195313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf("ARPING %s ", inet_ntoa(dst)); 1196313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf("from %s %s\n", inet_ntoa(src), device.name ? : ""); 1197313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1198313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1199313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!src.s_addr && !dad) { 1200313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti fprintf(stderr, "arping: no source address in not-DAD mode\n"); 1201313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(2); 1202313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1203313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1204313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti drop_capabilities(); 1205313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1206313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti set_signal(SIGINT, finish); 1207313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti set_signal(SIGALRM, catcher); 1208313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1209313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti catcher(); 1210313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1211313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti while(1) { 1212313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sigset_t sset, osset; 1213313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti unsigned char packet[4096]; 1214313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct sockaddr_storage from; 1215313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti socklen_t alen = sizeof(from); 1216313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int cc; 1217313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1218313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if ((cc = recvfrom(s, packet, sizeof(packet), 0, 1219313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (struct sockaddr *)&from, &alen)) < 0) { 1220313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("arping: recvfrom"); 1221313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti continue; 1222313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1223313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1224313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sigemptyset(&sset); 1225313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sigaddset(&sset, SIGALRM); 1226313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sigaddset(&sset, SIGINT); 1227313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sigprocmask(SIG_BLOCK, &sset, &osset); 1228313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti recv_pack(packet, cc, (struct sockaddr_ll *)&from); 1229313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sigprocmask(SIG_SETMASK, &osset, NULL); 1230313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1231313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 1232313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1233313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1234