1 /* $Id: getifaddr.c,v 1.14 2011/05/02 23:50:52 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
;
61 s
= socket(PF_INET
, SOCK_DGRAM
, 0);
64 DPRINTF(E_ERROR
, L_GENERAL
, "socket(PF_INET, SOCK_DGRAM): %s\n", strerror(errno
));
67 strncpy(ifr
.ifr_name
, ifname
, IFNAMSIZ
);
68 if(ioctl(s
, SIOCGIFADDR
, &ifr
, &ifrlen
) < 0)
70 DPRINTF(E_ERROR
, L_GENERAL
, "ioctl(s, SIOCGIFADDR, ...): %s\n", strerror(errno
));
74 addr
= (struct sockaddr_in
*)&ifr
.ifr_addr
;
75 if(!inet_ntop(AF_INET
, &addr
->sin_addr
, buf
, len
))
77 DPRINTF(E_ERROR
, L_GENERAL
, "inet_ntop(): %s\n", strerror(errno
));
81 if(ioctl(s
, SIOCGIFNETMASK
, &ifr
, &ifrlen
) == 0)
83 addr
= (struct sockaddr_in
*)&ifr
.ifr_netmask
;
84 mask
= ntohl(addr
->sin_addr
.s_addr
);
85 for (i
= 0; i
< 32; i
++)
94 snprintf(buf
+i
, len
-i
, "/%u", mask
);
98 DPRINTF(E_ERROR
, L_GENERAL
, "ioctl(s, SIOCGIFNETMASK, ...): %s\n", strerror(errno
));
104 getsysaddr(char * buf
, int len
)
107 int s
= socket(PF_INET
, SOCK_STREAM
, 0);
108 struct sockaddr_in addr
;
113 for (i
=1; i
> 0; i
++)
116 if( ioctl(s
, SIOCGIFNAME
, &ifr
) < 0 )
118 if(ioctl(s
, SIOCGIFADDR
, &ifr
, sizeof(struct ifreq
)) < 0)
120 memcpy(&addr
, &ifr
.ifr_addr
, sizeof(addr
));
121 if(strncmp(inet_ntoa(addr
.sin_addr
), "127.", 4) == 0)
123 if(ioctl(s
, SIOCGIFNETMASK
, &ifr
, sizeof(struct ifreq
)) < 0)
125 if(!inet_ntop(AF_INET
, &addr
.sin_addr
, buf
, len
))
127 DPRINTF(E_ERROR
, L_GENERAL
, "inet_ntop(): %s\n", strerror(errno
));
133 memcpy(&addr
, &ifr
.ifr_netmask
, sizeof(addr
));
134 mask
= ntohl(addr
.sin_addr
.s_addr
);
135 for (i
= 0; i
< 32; i
++)
144 snprintf(buf
+i
, len
-i
, "/%u", mask
);
154 getsyshwaddr(char * buf
, int len
)
156 struct if_nameindex
*ifaces
, *if_idx
;
157 unsigned char mac
[6];
162 memset(&mac
, '\0', sizeof(mac
));
163 /* Get the spatially unique node identifier */
164 fd
= socket(AF_INET
, SOCK_DGRAM
, 0);
168 ifaces
= if_nameindex();
172 for(if_idx
= ifaces
; if_idx
->if_index
; if_idx
++)
174 strncpy(ifr
.ifr_name
, if_idx
->if_name
, IFNAMSIZ
);
175 if(ioctl(fd
, SIOCGIFFLAGS
, &ifr
) < 0)
177 if(ifr
.ifr_ifru
.ifru_flags
& IFF_LOOPBACK
)
179 if( ioctl(fd
, SIOCGIFHWADDR
, &ifr
) < 0 )
181 if( MACADDR_IS_ZERO(ifr
.ifr_hwaddr
.sa_data
) )
186 if_freenameindex(ifaces
);
193 memmove(mac
, ifr
.ifr_hwaddr
.sa_data
, 6);
194 sprintf(buf
, "%02x%02x%02x%02x%02x%02x",
195 mac
[0]&0xFF, mac
[1]&0xFF, mac
[2]&0xFF,
196 mac
[3]&0xFF, mac
[4]&0xFF, mac
[5]&0xFF);
200 memmove(buf
, ifr
.ifr_hwaddr
.sa_data
, 6);
207 get_remote_mac(struct in_addr ip_addr
, unsigned char * mac
)
209 struct in_addr arp_ent
;
212 int matches
, hwtype
, flags
;
213 memset(mac
, 0xFF, 6);
215 arp
= fopen("/proc/net/arp", "r");
220 matches
= fscanf(arp
, "%15s 0x%8X 0x%8X %2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx",
221 remote_ip
, &hwtype
, &flags
,
222 &mac
[0], &mac
[1], &mac
[2], &mac
[3], &mac
[4], &mac
[5]);
225 inet_pton(AF_INET
, remote_ip
, &arp_ent
);
226 if( ip_addr
.s_addr
== arp_ent
.s_addr
)
234 memset(mac
, 0xFF, 6);