blob: a92848072efa08c10f2c34db72f725ff434b3dfe [file] [log] [blame]
Benny Prijonob681a2f2007-03-25 18:44:51 +00001/* $Id$ */
2/*
3 * Copyright (C)2003-2007 Benny Prijono <benny@prijono.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19#include <pj/ip_helper.h>
20#include <pj/addr_resolv.h>
21#include <pj/assert.h>
22#include <pj/errno.h>
23#include <pj/string.h>
Benny Prijono0ae59ae2007-11-17 10:27:34 +000024#include <pj/compat/socket.h>
Benny Prijonob681a2f2007-03-25 18:44:51 +000025
Benny Prijono0ae59ae2007-11-17 10:27:34 +000026static pj_status_t dummy_enum_ip_interface(unsigned *p_cnt,
27 pj_in_addr ifs[])
Benny Prijonob681a2f2007-03-25 18:44:51 +000028{
29 pj_status_t status;
30
31 PJ_ASSERT_RETURN(p_cnt && *p_cnt > 0 && ifs, PJ_EINVAL);
32
33 pj_bzero(ifs, sizeof(ifs[0]) * (*p_cnt));
34
35 /* Just get one default route */
Benny Prijono4c8fb532007-11-26 05:36:18 +000036 status = pj_getdefaultipinterface(&ifs[0]);
Benny Prijonob681a2f2007-03-25 18:44:51 +000037 if (status != PJ_SUCCESS)
38 return status;
39
40 *p_cnt = 1;
41 return PJ_SUCCESS;
42}
43
Benny Prijono0ae59ae2007-11-17 10:27:34 +000044#ifdef SIOCGIFCONF
45static pj_status_t sock_enum_ip_interface(unsigned *p_cnt,
46 pj_in_addr ifs[])
47{
48 pj_sock_t sock;
49 char buf[512];
50 struct ifconf ifc;
51 struct ifreq *ifr;
52 int i, count;
53 pj_status_t status;
54
55 status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &sock);
56 if (status != PJ_SUCCESS)
57 return status;
58
59 /* Query available interfaces */
60 ifc.ifc_len = sizeof(buf);
61 ifc.ifc_buf = buf;
62
63 if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
64 int oserr = pj_get_netos_error();
65 pj_sock_close(sock);
66 return PJ_RETURN_OS_ERROR(oserr);
67 }
68
69 /* Done with socket */
70 pj_sock_close(sock);
71
72 /* Interface interfaces */
73 ifr = (struct ifreq*) ifc.ifc_req;
74 count = ifc.ifc_len / sizeof(struct ifreq);
75 if (count > *p_cnt)
76 count = *p_cnt;
77 else
78 *p_cnt = count;
79 for (i=0; i<count; ++i) {
80 struct ifreq *itf = &ifr[i];
81 ifs[i].s_addr = ((struct sockaddr_in *)&itf->ifr_addr)->sin_addr.s_addr;
82 }
83
84 return PJ_SUCCESS;
85}
86#endif /* SIOCGIFCONF */
87
88/*
89 * Enumerate the local IP interface currently active in the host.
90 */
91PJ_DEF(pj_status_t) pj_enum_ip_interface(unsigned *p_cnt,
92 pj_in_addr ifs[])
93{
94#ifdef SIOCGIFCONF
95 if (sock_enum_ip_interface(p_cnt, ifs) == PJ_SUCCESS)
96 return PJ_SUCCESS;
97#endif
98 return dummy_enum_ip_interface(p_cnt, ifs);
99}
100
Benny Prijonob681a2f2007-03-25 18:44:51 +0000101/*
102 * Enumerate the IP routing table for this host.
103 */
104PJ_DEF(pj_status_t) pj_enum_ip_route(unsigned *p_cnt,
105 pj_ip_route_entry routes[])
106{
107 pj_status_t status;
108
109 PJ_ASSERT_RETURN(p_cnt && *p_cnt > 0 && routes, PJ_EINVAL);
110
111 pj_bzero(routes, sizeof(routes[0]) * (*p_cnt));
112
113 /* Just get one default route */
Benny Prijono4c8fb532007-11-26 05:36:18 +0000114 status = pj_getdefaultipinterface(&routes[0].ipv4.if_addr);
Benny Prijonob681a2f2007-03-25 18:44:51 +0000115 if (status != PJ_SUCCESS)
116 return status;
117
118 routes[0].ipv4.dst_addr.s_addr = 0;
119 routes[0].ipv4.mask.s_addr = 0;
120 *p_cnt = 1;
121
122 return PJ_SUCCESS;
123}
124