2
* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
5
* Copyright (C) 2003 Abdelkader Lahmadi <Abdelkader.Lahmadi@loria.fr>
6
* Olivier Festor <Olivier.Festor@loria.fr>
7
* Copyright (C) 2003-04 Luca Deri <deri@ntop.org>
9
* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
11
* This program is free software; you can redistribute it and/or modify
12
* it under the terms of the GNU General Public License as published by
13
* the Free Software Foundation; either version 2 of the License, or
14
* (at your option) any later version.
16
* This program is distributed in the hope that it will be useful,
17
* but WITHOUT ANY WARRANTY; without even the implied warranty of
18
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
* GNU General Public License for more details.
21
* You should have received a copy of the GNU General Public License
22
* along with this program; if not, write to the Free Software Foundation,
23
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
33
#define SA(saddr) ((struct sockaddr *)saddr)
34
#define SA4(saddr) ((struct sockaddr_in *)saddr)
35
#define IN4(saddr) (&SA4(saddr)->sin_addr)
36
#define SA6(saddr) ((struct sockaddr_in6 *)saddr)
37
#define IN6(saddr) (&SA6(saddr)->sin6_addr)
40
static struct in6_addr *in6_cpy(struct in6_addr *dst, struct in6_addr *src) {
41
return memcpy(dst, src, sizeof(struct in6_addr));
44
static struct in_addr *in4_cpy(struct in_addr *dst, struct in_addr *src) {
45
return memcpy(dst, src, sizeof(struct in_addr));
48
static str2in6_addr(char *str, struct in6_addr *addr){
52
for (i=0; i < 16; i++){
53
sscanf(str + (i*2), "%02x",&x);
54
addr->s6_addr[i]= x & 0xff;
57
static int prefixlen(void *val, int size) {
58
unsigned char *name = (unsigned char *)val;
59
int byte, bit, plen = 0;
61
for (byte = 0; byte < size; byte++, plen += 8)
62
if (name[byte] != 0xff)
66
for (bit = 7; bit != 0; bit--, plen++)
67
if (!(name[byte] & (1 << bit)))
69
for (; bit != 0; bit--)
70
if (name[byte] & (1 << bit))
73
for (; byte < size; byte++)
79
/* ************************************************* */
81
#if defined(HAVE_IFLIST_SYSCTL) && defined(HAVE_SYSCTL)
83
struct iface_handler *iface_new(void) {
84
int mib[6] = { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0 };
88
struct iface_handler *hdlr = NULL;
92
struct iface_addr *ia;
94
/* Allocate memory for iface handler
96
if (! (hdlr = (struct iface_handler *)calloc(1,sizeof(struct iface_handler)))) {
101
/* Retrieve raw interface information buffer
103
if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
105
if (! (buf = malloc(needed))) {
109
if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
113
/* Count interfaces and addresses
118
struct if_msghdr *ifm = (struct if_msghdr *)next;
119
if (ifm->ifm_type != RTM_IFINFO)
122
next += ifm->ifm_msglen;
124
struct if_msghdr *nextifm = (struct if_msghdr *)next;
125
if (nextifm->ifm_type != RTM_NEWADDR)
127
next += nextifm->ifm_msglen;
133
/* Allocate memory for storing interfaces/addresses lists
135
if ((! (hdlr->if_list = (struct iface_if *)calloc(hdlr->if_count,sizeof(struct iface_if)))) ||
136
(! (hdlr->addr_list = (struct iface_addr *)calloc(hdlr->addr_count,sizeof(struct iface_addr))))) {
142
/* Parsing raw buffer
147
struct iface_if *ii = &hdlr->if_list[if_pos];
148
struct if_msghdr *ifm = (struct if_msghdr *)next;
149
struct sockaddr_dl *sdl = (struct sockaddr_dl *)(ifm + 1);
154
if (ifm->ifm_type != RTM_IFINFO) {
159
/* Interface name and index
161
ii->next = &hdlr->if_list[if_pos+1];
163
ii->index = ifm->ifm_index;
164
strncpy(ii->name, sdl->sdl_data, sdl->sdl_nlen);
165
ii->name[sdl->sdl_nlen] = '\0';
168
* UP / BROADCAST / MULTICAST / LOOPBACK / P2P / PROMISC / SIMPLEX
170
if (ifm->ifm_flags & IFF_UP) /* interface is UP */
171
ii->info |= IFACE_INFO_UP;
172
if (ifm->ifm_flags & IFF_LOOPBACK) /* is a loopback net */
173
ii->info |= IFACE_INFO_LOOPBACK;
174
if (ifm->ifm_flags & IFF_POINTOPOINT) /* point to point link */
175
ii->info |= IFACE_INFO_P2P;
176
if (ifm->ifm_flags & IFF_BROADCAST) /* support broadcast */
177
ii->info |= IFACE_INFO_BROADCAST;
178
if (ifm->ifm_flags & IFF_MULTICAST) /* support multicast */
179
ii->info |= IFACE_INFO_MULTICAST;
180
if (ifm->ifm_flags & IFF_PROMISC) /* receive all packets */
181
ii->info |= IFACE_INFO_PROMISC;
182
/*if (ifm->ifm_flags & IFF_SIMPLEX)*/ /* can't hear own packets */
183
/* ii->info |= IFACE_INFO_SIMPLEX;*/
185
/* Information about physical interface
186
* type / physaddr / addrlen
188
ii->type = sdl->sdl_type; // ::TODO:: type conversion
189
if (sdl->sdl_alen > 0) {
190
ii->phys.size = sdl->sdl_alen;
191
ii->phys.addr = malloc(ii->phys.size);
192
if (ii->phys.addr == NULL) {
196
memcpy(ii->phys.addr, LLADDR(sdl), ii->phys.size);
199
/* Retrieve addresses
201
ii->addrs = &hdlr->addr_list[addr_pos];
203
next += ifm->ifm_msglen;
205
struct sockaddr *sa[RTAX_MAX];
206
struct if_msghdr *nextifm = (struct if_msghdr *)next;
207
struct ifa_msghdr *ifam = (struct ifa_msghdr *)nextifm;
208
char *cp = (char *)(ifam + 1);
212
if (nextifm->ifm_type != RTM_NEWADDR)
215
/* Unpack address information
217
memset(sa, 0, sizeof(sa));
218
for (i = 0; (i < RTAX_MAX) && (cp < lim); i++) {
219
if ((ifam->ifam_addrs & (1 << i)) == 0)
222
cp += ROUNDUP(sa[i]->sa_len);
225
/* Basic information about interface
227
ia = &hdlr->addr_list[addr_pos];
230
ia->next = &hdlr->addr_list[addr_pos+1];
232
/* Process accroding to address family
235
ia->family = sa[RTAX_IFA]->sa_family;
238
in4_cpy(&ia->af.inet.addr, IN4(sa[RTAX_IFA]));
239
in4_cpy(&ia->af.inet.bcast,
240
sa[RTAX_BRD]?IN4(sa[RTAX_BRD]):IN4(sa[RTAX_IFA]));
241
ia->af.inet.mask = sa[RTAX_NETMASK]
242
? prefixlen(IN4(sa[RTAX_NETMASK]),sizeof(struct in_addr))
243
: 8 * sizeof(struct in_addr);
246
in6_cpy(&ia->af.inet6.addr, IN6(sa[RTAX_IFA]));
247
ia->af.inet6.prefixlen = sa[RTAX_NETMASK]
248
? prefixlen(IN6(sa[RTAX_NETMASK]),sizeof(struct in6_addr))
249
: 8 * sizeof(struct in6_addr);
252
/* Don't know how to process it, so ignore it
258
next += nextifm->ifm_msglen;
268
hdlr->if_list[hdlr->if_count-1].next = NULL;
281
/* TODO: Using ioctl for getting interface addresses */
283
#define PATH_PROC_NET_IF_INET6 "/proc/net/if_inet6"
284
static int iface_getflags(struct iface_if *ii) {
288
strncpy(lifreq.ifr_name, ii->name,IFNAMSIZ);
289
lifreq.ifr_addr.sa_family = AF_INET;
290
if ((sock = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
292
/* Interface flags */
293
if (ioctl(sock, SIOCGIFFLAGS,&lifreq) < 0)
295
if (lifreq.ifr_flags & IFF_UP) /* interface is UP */
296
ii->info |= IFACE_INFO_UP;
297
if (lifreq.ifr_flags & IFF_LOOPBACK) /* is a loopback net */
298
ii->info |= IFACE_INFO_LOOPBACK;
299
if (lifreq.ifr_flags & IFF_POINTOPOINT) /* point to point link */
300
ii->info |= IFACE_INFO_P2P;
301
if (lifreq.ifr_flags & IFF_BROADCAST) /* support broadcast */
302
ii->info |= IFACE_INFO_BROADCAST;
303
if (lifreq.ifr_flags & IFF_MULTICAST) /* support multicast */
304
ii->info |= IFACE_INFO_MULTICAST;
305
if (lifreq.ifr_flags & IFF_PROMISC) /* receive all packets */
306
ii->info |= IFACE_INFO_PROMISC;
310
/* **************************************************** */
312
struct iface_handler *iface_new(void) {
317
int ifindex, plen, scope, status;
319
struct iface_handler * hdlr;
322
struct iface_if *ii, *itf;
323
struct iface_addr *ia, *it;
324
struct in6_addr addr;
326
/* Allocate memory for iface handler
328
if (! (hdlr = (struct iface_handler *)calloc(1,sizeof(struct iface_handler)))){
332
fp = fopen(PATH_PROC_NET_IF_INET6,"r");
335
hdlr->if_list = ii = NULL;
336
hdlr->addr_list = ia = NULL;
337
while (fgets(buf, 1024, fp) != NULL){
338
n = sscanf(buf, "%32s %02x %02x %02x %02x %20s",
339
straddr, &ifindex,&plen, &scope, &status, ifname);
342
str2in6_addr(straddr, &addr);
343
/* search existing interface */
344
for (itf = hdlr->if_list;itf; itf= itf->next){
345
if (strncmp(itf->name, ifname,IFNAMSIZ) == 0){
346
/* update addresses*/
347
for (it = itf->addrs;it->next != NULL ; it = it->next);
348
ia = (struct iface_addr *) malloc(sizeof(struct iface_addr));
349
ia->family = AF_INET6;
351
in6_cpy(&ia->af.inet6.addr, &addr);
352
ia->af.inet6.prefixlen = plen;
359
/* New interface/ address */
360
itf = (struct iface_if *)malloc(sizeof(struct iface_if));
362
memcpy(itf->name, ifname, IFNAMSIZ);
363
itf->index = ifindex;
365
it = itf->addrs =(struct iface_addr *) malloc(sizeof(struct iface_addr));
366
it->family = AF_INET6;
368
in6_cpy(&it->af.inet6.addr, &addr);
369
it->af.inet6.prefixlen = plen;
373
hdlr->addr_list = it;
391
struct iface_handler *iface_new(void) {
397
/* ******************************************************* */
399
void iface_destroy(struct iface_handler *hdlr) {
402
free(hdlr->addr_list);
404
#if defined(HAVE_IFLIST_SYSCTL) && defined(HAVE_SYSCTL)
406
for (i = 0 ; i < hdlr->if_count ; i++)
407
if (hdlr->if_list[i].phys.addr)
408
free(hdlr->if_list[i].phys.addr);
416
int iface_addrcount(struct iface_handler *hdlr) {
417
return hdlr->addr_count;
421
int iface_ifcount(struct iface_handler *hdlr) {
422
return hdlr->if_count;
426
struct iface_if *iface_getif_first(struct iface_handler *hdlr) {
427
return hdlr->if_count ? &hdlr->if_list[0] : NULL;
431
struct iface_if *iface_getif_next(struct iface_if *ii) {
432
return ii ? ii->next : NULL;
436
int iface_if_addrcount(struct iface_if *ii, int family) {
437
struct iface_addr *ia;
440
for (ia = ii->addrs ; ia ; ia = ia->next)
441
if (!family || (ia->family == family))
448
struct iface_if *iface_getif_byindex(struct iface_handler *hdlr, int idx) {
451
for (i = 0 ; i < hdlr->if_count ; i++)
452
if (hdlr->if_list[i].index == idx)
453
return &hdlr->if_list[i];
458
struct iface_if *iface_getif_byname(struct iface_handler *hdlr, char *name) {
461
for (i = 0 ; i < hdlr->if_count ; i++)
462
if (! strcmp(hdlr->if_list[i].name, name))
463
return &hdlr->if_list[i];
468
char *iface_if_getname(struct iface_if *ii, char *name, int size) {
471
strncpy(name, ii->name, size);
473
name = strdup(ii->name);
478
int iface_if_getindex(struct iface_if *ii) {
484
int iface_if_getinfo(struct iface_if *ii) {
489
int iface_if_gettype(struct iface_if *ii) {
495
int iface_if_getphys(struct iface_if *ii,int *type,char *addr,int *addrsize) {
499
*addrsize = *addrsize < ii->phys.size ? *addrsize : ii->phys.size;
501
memcpy(addr, ii->phys.addr, *addrsize);
503
return ii->phys.size;
507
struct iface_addr *iface_getaddr_first(struct iface_if *ii, int family) {
508
struct iface_addr *ia;
510
if (! (ia = ii->addrs))
512
if (family && (ia->family != family))
513
return iface_getaddr_next(ia, family);
517
struct iface_addr *iface_getaddr_next(struct iface_addr *ia, int family) {
521
} while (ia && family && (ia->family != family));
526
int iface_addr_getfamily(struct iface_addr *ia) {
531
int iface_addr_ifindex(struct iface_addr *ia) {
532
return ia->ifi->index;
536
void *iface_addr_getinfo(struct iface_addr *ia, void *infobuf) {
539
memcpy(infobuf, &ia->af.inet, sizeof(struct iface_addr_inet));
542
memcpy(infobuf, &ia->af.inet6, sizeof(struct iface_addr_inet6));
549
/* *************************************************** */
551
int iface6(int *idx, int size) {
553
struct iface_handler *ih;
562
for (ii = iface_getif_first(ih) ; ii ; ii = iface_getif_next(ii))
563
if ((iface_if_getinfo(ii) & (IFACE_INFO_UP | IFACE_INFO_LOOPBACK)) ==
565
if (iface_getaddr_first(ii, AF_INET6)) {
569
*idx++ = iface_if_getindex(ii);
580
// check for using only SIOCGIF* instead of sysctl, it seems more
584
#define ESTIMATED_LOCAL 20
587
/*@brief expand sockaddr's included in <code>ifam</code>
589
*@param ifam message containing information about interface
591
*@param ai structure where addresses will be expanded.
595
void iface_unpackaddr(struct ifa_msghdr *ifam, struct rt_addrinfo *ai){
599
wp = (char *)(ifam + 1);
601
ai->rti_addrs = ifam->ifam_addrs;
602
for (rtax = 0; rtax < sizeof ai->rti_info / sizeof *ai->rti_info; rtax++)
603
if (ifam->ifam_addrs & (1 << rtax)) {
604
ai->rti_info[rtax] = (struct sockaddr *)wp;
605
wp += ROUNDUP(ai->rti_info[rtax]->sa_len);
607
ai->rti_info[rtax] = NULL;
611
/*@ find all IP interfaces addreses
613
*@param type adresses family (AF_INET / AF_INET6)
614
*@param size number of addresses found
615
*@param addr buffer of list of adresses should be IPv4/IPv6
618
int iface_getalladdr(int type, int *size, char **addr){
619
int mib[6], n, s, alloced;
621
char *buf, *end, *ptr;
622
struct if_msghdr *ifm;
623
struct ifa_msghdr *ifam;
624
struct rt_addrinfo ai;
626
struct sockaddr_dl *dl;
627
struct sockaddr_in6 *sin;
629
struct in6_addr *saddr;
633
mib[4] = NET_RT_IFLIST;
634
mib[2] = mib[3] = mib[5] = 0;
636
if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
638
if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
640
if ((buf = (char *)malloc(needed)) == NULL)
642
if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
648
for (ptr = buf; ptr < end; ptr += ifm->ifm_msglen) {
649
ifm = (struct if_msghdr *)ptr;
650
dl = (struct sockaddr_dl *)(ifm + 1);
651
if (ifm->ifm_index != dl->sdl_index || dl->sdl_nlen == 0)
652
/* Skip over remaining ifa_msghdrs */
654
n = dl->sdl_nlen > sizeof(ifr.ifr_name) ?
655
sizeof(ifr.ifr_name) : dl->sdl_nlen;
656
strncpy(ifr.ifr_name, dl->sdl_data, n);
657
if (n < sizeof (ifr.ifr_name))
658
ifr.ifr_name[n] = '\0';
659
if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0)
661
else if (ifr.ifr_flags & IFF_UP) {
662
ifam = (struct ifa_msghdr *)(ptr + ifm->ifm_msglen);
663
while ((char *)ifam < end && ifam->ifam_type == RTM_NEWADDR) {
664
iface_unpackaddr(ifam, &ai);
667
if (ai.rti_info[RTAX_IFA] != NULL &&
668
ai.rti_info[RTAX_IFA]->sa_family == AF_INET) {
669
if (alloced < num_local + 1) {
670
alloced += ESTIMATED_LOCAL;
671
saddr = (struct in_addr *)realloc(saddr, alloced * sizeof(struct in_addr));
678
memcpy((struct in_addr *)&saddr[num_local++],
679
&(((struct sockaddr_in *)ai.rti_info[RTAX_IFA])->sin_addr),
680
sizeof(struct in_addr));
684
if (ai.rti_info[RTAX_IFA] != NULL &&
685
ai.rti_info[RTAX_IFA]->sa_family == AF_INET6) {
686
sin = (struct sockaddr_in6 *)ai.rti_info[RTAX_IFA];
687
if (!IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr) &&
688
!IN6_IS_ADDR_LOOPBACK(&sin->sin6_addr)){
689
if (alloced < num_local + 1) {
690
alloced += ESTIMATED_LOCAL;
691
saddr = (struct in6_addr *)realloc(saddr, alloced * sizeof saddr[0]);
699
memcpy(&saddr[num_local++],&sin->sin6_addr, sizeof(struct in6_addr));
705
ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen);
712
*addr = (char *)saddr;