1 /* $Id: getifaddr.c,v 1.12 2010/11/11 23:48:13 jmaggard Exp $ */
3 * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
5 * Copyright (c) 2006, Thomas Bernard
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * * The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
34 #include <sys/ioctl.h>
35 #include <sys/types.h>
36 #include <sys/socket.h>
38 #include <arpa/inet.h>
39 #include <netinet/in.h>
43 #include <sys/sockio.h>
46 #include "getifaddr.h"
50 getifaddr(const char * ifname
, char * buf
, int len
)
52 /* SIOCGIFADDR struct ifreq * */
56 struct sockaddr_in
* addr
;
58 s
= socket(PF_INET
, SOCK_DGRAM
, 0);
61 DPRINTF(E_ERROR
, L_GENERAL
, "socket(PF_INET, SOCK_DGRAM): %s\n", strerror(errno
));
64 strncpy(ifr
.ifr_name
, ifname
, IFNAMSIZ
);
65 if(ioctl(s
, SIOCGIFADDR
, &ifr
, &ifrlen
) < 0)
67 DPRINTF(E_ERROR
, L_GENERAL
, "ioctl(s, SIOCGIFADDR, ...): %s\n", strerror(errno
));
71 addr
= (struct sockaddr_in
*)&ifr
.ifr_addr
;
72 if(!inet_ntop(AF_INET
, &addr
->sin_addr
, buf
, len
))
74 DPRINTF(E_ERROR
, L_GENERAL
, "inet_ntop(): %s\n", strerror(errno
));
83 getsysaddr(char * buf
, int len
)
86 int s
= socket(PF_INET
, SOCK_STREAM
, 0);
87 struct sockaddr_in addr
;
94 if( ioctl(s
, SIOCGIFNAME
, &ifr
) < 0 )
96 if(ioctl(s
, SIOCGIFADDR
, &ifr
, sizeof(struct ifreq
)) < 0)
98 memcpy(&addr
, &ifr
.ifr_addr
, sizeof(addr
));
99 if(strncmp(inet_ntoa(addr
.sin_addr
), "127.", 4) == 0)
101 if(!inet_ntop(AF_INET
, &addr
.sin_addr
, buf
, len
))
103 DPRINTF(E_ERROR
, L_GENERAL
, "inet_ntop(): %s\n", strerror(errno
));
116 getsyshwaddr(char * buf
, int len
)
118 struct if_nameindex
*ifaces
, *if_idx
;
119 unsigned char mac
[6];
124 memset(&mac
, '\0', sizeof(mac
));
125 /* Get the spatially unique node identifier */
126 fd
= socket(AF_INET
, SOCK_DGRAM
, 0);
130 ifaces
= if_nameindex();
134 for(if_idx
= ifaces
; if_idx
->if_index
; if_idx
++)
136 strncpy(ifr
.ifr_name
, if_idx
->if_name
, IFNAMSIZ
);
137 if(ioctl(fd
, SIOCGIFFLAGS
, &ifr
) < 0)
139 if(ifr
.ifr_ifru
.ifru_flags
& IFF_LOOPBACK
)
141 if( ioctl(fd
, SIOCGIFHWADDR
, &ifr
) < 0 )
143 if( MACADDR_IS_ZERO(ifr
.ifr_hwaddr
.sa_data
) )
148 if_freenameindex(ifaces
);
155 memmove(mac
, ifr
.ifr_hwaddr
.sa_data
, 6);
156 sprintf(buf
, "%02x%02x%02x%02x%02x%02x",
157 mac
[0]&0xFF, mac
[1]&0xFF, mac
[2]&0xFF,
158 mac
[3]&0xFF, mac
[4]&0xFF, mac
[5]&0xFF);
162 memmove(buf
, ifr
.ifr_hwaddr
.sa_data
, 6);
169 get_remote_mac(struct in_addr ip_addr
, unsigned char * mac
)
171 struct in_addr arp_ent
;
174 int matches
, hwtype
, flags
;
175 memset(mac
, 0xFF, 6);
177 arp
= fopen("/proc/net/arp", "r");
182 matches
= fscanf(arp
, "%s 0x%X 0x%X %hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
183 remote_ip
, &hwtype
, &flags
,
184 &mac
[0], &mac
[1], &mac
[2], &mac
[3], &mac
[4], &mac
[5]);
187 inet_pton(AF_INET
, remote_ip
, &arp_ent
);
188 if( ip_addr
.s_addr
== arp_ent
.s_addr
)
196 memset(mac
, 0xFF, 6);