1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
/* $OpenBSD: ifaddr.c,v 1.5 2000/04/05 05:35:28 kjell Exp $ */
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <err.h>
#include <stdlib.h>
#include <unistd.h>
#include "ifaddr.h"
/*
* if_addr():
* given a string containing an interface name (e.g. "ppp0")
* return the IP address it represents
*
* The OpenBSD community considers this feature to be quite useful and
* suggests inclusion into other platforms. The closest alternative is
* to define /etc/networks with suitable values.
*/
int if_addr(name, ap)
char *name;
struct in_addr *ap;
{
struct ifconf ifc;
struct ifreq ifreq, *ifr;
char *inbuf = NULL;
int s, i, len = 8192;
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
warn("socket");
return 0;
}
while (1) {
ifc.ifc_len = len;
ifc.ifc_buf = inbuf = realloc(inbuf, len);
if (inbuf == NULL)
err(1, "malloc");
if (ioctl(s, SIOCGIFCONF, &ifc) < 0) {
warn("SIOCGIFCONF");
goto if_addr_lose;
}
if (ifc.ifc_len + sizeof(ifreq) < len)
break;
len *= 2;
}
ifr = ifc.ifc_req;
ifreq.ifr_name[0] = '\0';
for (i = 0; i < ifc.ifc_len; ) {
ifr = (struct ifreq *)((caddr_t)ifc.ifc_req + i);
i += sizeof(ifr->ifr_name) +
(ifr->ifr_addr.sa_len > sizeof(struct sockaddr)
? ifr->ifr_addr.sa_len
: sizeof(struct sockaddr));
ifreq = *ifr;
if (ioctl(s, SIOCGIFADDR, (caddr_t)ifr) < 0)
continue;
if (ifr->ifr_addr.sa_family != AF_INET)
continue;
if (!strcmp(name, ifr->ifr_name)) {
struct sockaddr_in *sin;
close(s);
free(inbuf);
sin = (struct sockaddr_in *)&ifr->ifr_addr;
*ap = sin->sin_addr;
return (1);
}
}
if_addr_lose:
close(s);
free(inbuf);
return 0;
}
|