* $Id: libnet_if_addr.c,v 1.21 2005/11/29 21:56:10 carlosc Exp $
* libnet_if_addr.c - interface selection code
* Copyright (c) 1998 - 2004 Mike D. Schiffman <mike@infonexus.com>
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
#include "../include/config.h"
#if (!(_WIN32) || (__CYGWIN__))
#include "../include/libnet.h"
#include "../include/win32/libnet.h"
#include "../include/ifaddrlist.h"
* By testing if we can retrieve the FLAGS of an iface
* we can know if it exists or not and if it is up.
libnet_check_iface(libnet_t
*l
)
fd
= socket(AF_INET
, SOCK_DGRAM
, 0);
snprintf(l
->err_buf
, LIBNET_ERRBUF_SIZE
, "%s() socket: %s\n", __func__
,
strncpy(ifr
.ifr_name
, l
->device
, sizeof(ifr
.ifr_name
) -1);
ifr
.ifr_name
[sizeof(ifr
.ifr_name
) - 1] = '\0';
res
= ioctl(fd
, SIOCGIFFLAGS
, (int8_t *)&ifr
);
snprintf(l
->err_buf
, LIBNET_ERRBUF_SIZE
, "%s() ioctl: %s\n", __func__
,
if ((ifr
.ifr_flags
& IFF_UP
) == 0)
snprintf(l
->err_buf
, LIBNET_ERRBUF_SIZE
, "%s(): %s is down\n",
* Return the interface list
#ifdef HAVE_SOCKADDR_SA_LEN
((struct ifreq *)((u_char *)&i->ifr_addr + i->ifr_addr.sa_len))
#define NEXTIFR(i) (i + 1)
#define PROC_DEV_FILE "/proc/net/dev"
libnet_ifaddrlist(register struct libnet_ifaddr_list
**ipaddrp
, int8_t *dev
,
register struct libnet_ifaddr_list
*al
;
struct ifreq
*ifr
, *lifr
, *pifr
, nifr
;
int8_t device
[sizeof(nifr
.ifr_name
)];
static struct libnet_ifaddr_list ifaddrlist
[MAX_IPADDR
];
struct ifreq ibuf
[MAX_IPADDR
];
register int fd
, nipaddr
;
fd
= socket(AF_INET
, SOCK_DGRAM
, 0);
snprintf(errbuf
, LIBNET_ERRBUF_SIZE
, "%s(): socket error: %s\n",
__func__
, strerror(errno
));
if ((fp
= fopen(PROC_DEV_FILE
, "r")) == NULL
)
snprintf(errbuf
, LIBNET_ERRBUF_SIZE
,
"%s(): fopen(proc_dev_file) failed: %s\n", __func__
,
memset(&ifc
, 0, sizeof(ifc
));
ifc
.ifc_len
= sizeof(ibuf
);
ifc
.ifc_buf
= (caddr_t
)ibuf
;
if(ioctl(fd
, SIOCGIFCONF
, &ifc
) < 0)
snprintf(errbuf
, LIBNET_ERRBUF_SIZE
,
"%s(): ioctl(SIOCGIFCONF) error: %s\n",
__func__
, strerror(errno
));
lifr
= (struct ifreq
*)&ifc
.ifc_buf
[ifc
.ifc_len
];
while (fgets(buf
, sizeof(buf
), fp
))
if ((p
= strchr(buf
, ':')) == NULL
)
for(p
= buf
; *p
== ' '; p
++) ;
strncpy(nifr
.ifr_name
, p
, sizeof(nifr
.ifr_name
) - 1);
nifr
.ifr_name
[sizeof(nifr
.ifr_name
) - 1] = '\0';
#else /* !HAVE_LINUX_PROCFS */
for (ifr
= ifc
.ifc_req
; ifr
< lifr
; ifr
= NEXTIFR(ifr
))
/* XXX LINUX SOLARIS ifalias */
if((p
= strchr(ifr
->ifr_name
, ':')))
if (pifr
&& strcmp(ifr
->ifr_name
, pifr
->ifr_name
) == 0)
strncpy(nifr
.ifr_name
, ifr
->ifr_name
, sizeof(nifr
.ifr_name
) - 1);
nifr
.ifr_name
[sizeof(nifr
.ifr_name
) - 1] = '\0';
strncpy(device
, nifr
.ifr_name
, sizeof(device
) - 1);
device
[sizeof(device
) - 1] = '\0';
if (ioctl(fd
, SIOCGIFFLAGS
, &nifr
) < 0)
if ((nifr
.ifr_flags
& IFF_UP
) == 0)
if (dev
== NULL
&& LIBNET_ISLOOPBACK(&nifr
))
strncpy(nifr
.ifr_name
, device
, sizeof(device
) - 1);
nifr
.ifr_name
[sizeof(nifr
.ifr_name
) - 1] = '\0';
if (ioctl(fd
, SIOCGIFADDR
, (int8_t *)&nifr
) < 0)
if (errno
!= EADDRNOTAVAIL
)
snprintf(errbuf
, LIBNET_ERRBUF_SIZE
,
"%s(): SIOCGIFADDR: dev=%s: %s\n", __func__
, device
,
else /* device has no IP address => set to 0 */
al
->addr
= ((struct sockaddr_in
*)&nifr
.ifr_addr
)->sin_addr
.s_addr
;
if ((al
->device
= strdup(device
)) == NULL
)
snprintf(errbuf
, LIBNET_ERRBUF_SIZE
,
"%s(): strdup not enough memory\n", __func__
);
#ifndef HAVE_LINUX_PROCFS
snprintf(errbuf
, LIBNET_ERRBUF_SIZE
,
"%s(): ferror: %s\n", __func__
, strerror(errno
));
/* From tcptraceroute, convert a numeric IP address to a string */
static int8_t *iptos(u_int32_t in
)
static int8_t output
[IPTOSBUFFERS
][ 3 * 4 + 3 + 1];
which
= (which
+ 1 == IPTOSBUFFERS
? 0 : which
+ 1);
snprintf(output
[which
], IPTOSBUFFERS
, "%d.%d.%d.%d",
libnet_ifaddrlist(register struct libnet_ifaddr_list
**ipaddrp
, int8_t *dev
,
int nipaddr
= 0; int i
= 0;
static struct libnet_ifaddr_list ifaddrlist
[MAX_IPADDR
];
int8_t err
[PCAP_ERRBUF_SIZE
];
/* Retrieve the interfaces list */
if (pcap_findalldevs(&alldevs
, err
) == -1)
snprintf(errbuf
, LIBNET_ERRBUF_SIZE
,
"%s(): error in pcap_findalldevs: %s\n", __func__
, err
);
/* Scan the list printing every entry */
for (d
= alldevs
; d
; d
= d
->next
)
if((!d
->addresses
) || (d
->addresses
->addr
->sa_family
!= AF_INET
))
if(d
->flags
& PCAP_IF_LOOPBACK
)
ifaddrlist
[i
].device
= strdup(d
->name
);
ifaddrlist
[i
].addr
= (u_int32_t
)
strdup(iptos(((struct sockaddr_in
*)
d
->addresses
->addr
)->sin_addr
.s_addr
));
libnet_select_device(libnet_t
*l
)
int8_t err_buf
[LIBNET_ERRBUF_SIZE
];
struct libnet_ifaddr_list
*address_list
, *al
;
if (l
->device
&& !isdigit(l
->device
[0]))
if (libnet_check_iface(l
) < 0)
/* err msg set in libnet_check_iface() */
c
= libnet_ifaddrlist(&address_list
, l
->device
, err_buf
);
/* err msg set in libnet_ifaddrlist() */
snprintf(l
->err_buf
, LIBNET_ERRBUF_SIZE
,
"%s(): no network interface found\n", __func__
);
* Then we have an IP address in l->device => do lookup
addr
= libnet_name2addr4(l
, l
->device
, 0);
for (i
= c
; i
; --i
, ++address_list
)
if (((addr
== -1) && !(strncmp(l
->device
, address_list
->device
,
(address_list
->addr
== addr
))
/* free the "user supplied device" - see libnet_init() */
l
->device
= strdup(address_list
->device
);
snprintf(l
->err_buf
, LIBNET_ERRBUF_SIZE
,
"%s(): can't find interface for IP %s\n", __func__
,
l
->device
= strdup(address_list
->device
);