Parsing ifconfig output is boring, so something like this could perhaps be added? I'm not adding it myself, since network/socket/ioctl-stuff isn't my best area.
static void f_gethostip(INT32 args) { int fd, i, j, up; struct ifconf ifc; struct sockaddr_in addr; char buffer[ INTERFACES * sizeof( struct ifreq ) ];
pop_n_elems(args);
fd = fd_socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ); if( fd < 0 ) Pike_error("gethostip: Failed to open socket.\n");
ifc.ifc_len = sizeof( buffer ); ifc.ifc_ifcu.ifcu_buf = (caddr_t)buffer; if( ioctl( fd, SIOCGIFCONF, &ifc ) < 0 ) Pike_error("gethostip: Query failed.\n");
up = 0; for( i=0; i<ifc.ifc_len; ) { struct ifreq *ifr = (struct ifreq *)( (caddr_t)ifc.ifc_req+i ); struct ifreq ifr2; i += sizeof(struct ifreq);
strcpy( ifr2.ifr_name, ifr->ifr_name ); if( ioctl( fd, SIOCGIFFLAGS, &ifr2 )<0 ) Pike_error("gethostip: Query failed.\n");
if( (ifr2.ifr_flags & IFF_LOOPBACK) || !(ifr2.ifr_flags & IFF_UP) || (ifr->ifr_addr.sa_family != AF_INET ) ) continue;
push_text( ifr->ifr_name ); memcpy( &addr, &ifr->ifr_addr, sizeof(ifr->ifr_addr) ); push_text( inet_ntoa( addr.sin_addr ) );
up++; } fd_close(fd); f_aggregate_mapping(up*2); }
How portable is SIOCGIFCONF? Solaris 9 seems to consider it obsolete, and provides SIOCGLIFCONF as a replacement. And for W*ndows something else completely is probably needed.
Otherwise it seems ok, but it should of course return IPV6 addresses as well. Which makes the proposed API a bit awkward, since each interface may have two addresses, one V4 and one V6.
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
Previous text:
2004-09-11 05:22: Subject: gethostip
Parsing ifconfig output is boring, so something like this could perhaps be added? I'm not adding it myself, since network/socket/ioctl-stuff isn't my best area.
static void f_gethostip(INT32 args) { int fd, i, j, up; struct ifconf ifc; struct sockaddr_in addr; char buffer[ INTERFACES * sizeof( struct ifreq ) ];
pop_n_elems(args);
fd = fd_socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ); if( fd < 0 ) Pike_error("gethostip: Failed to open socket.\n");
ifc.ifc_len = sizeof( buffer ); ifc.ifc_ifcu.ifcu_buf = (caddr_t)buffer; if( ioctl( fd, SIOCGIFCONF, &ifc ) < 0 ) Pike_error("gethostip: Query failed.\n");
up = 0; for( i=0; i<ifc.ifc_len; ) { struct ifreq *ifr = (struct ifreq *)( (caddr_t)ifc.ifc_req+i ); struct ifreq ifr2; i += sizeof(struct ifreq);
strcpy( ifr2.ifr_name, ifr->ifr_name ); if( ioctl( fd, SIOCGIFFLAGS, &ifr2 )<0 ) Pike_error("gethostip: Query failed.\n");
if( (ifr2.ifr_flags & IFF_LOOPBACK) || !(ifr2.ifr_flags & IFF_UP) || (ifr->ifr_addr.sa_family != AF_INET ) ) continue;
push_text( ifr->ifr_name ); memcpy( &addr, &ifr->ifr_addr, sizeof(ifr->ifr_addr) ); push_text( inet_ntoa( addr.sin_addr ) );
up++; } fd_close(fd); f_aggregate_mapping(up*2); }
/ Martin Nilsson (DivX Networks)
SIOCGICONG doesn't work excatly the same on *BSD. You should use getifaddrs() whenever possible, it is said to be cleaner and easier to use. getifaddrs is available on Darwin, *BSD and recent Linux.
/ David
Marcus Comstedt (ACROSS) (Hail Ilpalazzo!) @ Pike (-) developers forum wrote:
How portable is SIOCGIFCONF? Solaris 9 seems to consider it obsolete, and provides SIOCGLIFCONF as a replacement. And for W*ndows something else completely is probably needed.
Otherwise it seems ok, but it should of course return IPV6 addresses as well. Which makes the proposed API a bit awkward, since each interface may have two addresses, one V4 and one V6.
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
Previous text:
2004-09-11 05:22: Subject: gethostip
Parsing ifconfig output is boring, so something like this could perhaps be added? I'm not adding it myself, since network/socket/ioctl-stuff isn't my best area.
static void f_gethostip(INT32 args) { int fd, i, j, up; struct ifconf ifc; struct sockaddr_in addr; char buffer[ INTERFACES * sizeof( struct ifreq ) ];
pop_n_elems(args);
fd = fd_socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ); if( fd < 0 ) Pike_error("gethostip: Failed to open socket.\n");
ifc.ifc_len = sizeof( buffer ); ifc.ifc_ifcu.ifcu_buf = (caddr_t)buffer; if( ioctl( fd, SIOCGIFCONF, &ifc ) < 0 ) Pike_error("gethostip: Query failed.\n");
up = 0; for( i=0; i<ifc.ifc_len; ) { struct ifreq *ifr = (struct ifreq *)( (caddr_t)ifc.ifc_req+i ); struct ifreq ifr2; i += sizeof(struct ifreq);
strcpy( ifr2.ifr_name, ifr->ifr_name ); if( ioctl( fd, SIOCGIFFLAGS, &ifr2 )<0 ) Pike_error("gethostip: Query failed.\n");
if( (ifr2.ifr_flags & IFF_LOOPBACK) || !(ifr2.ifr_flags & IFF_UP) || (ifr->ifr_addr.sa_family != AF_INET ) ) continue;
push_text( ifr->ifr_name ); memcpy( &addr, &ifr->ifr_addr, sizeof(ifr->ifr_addr) ); push_text( inet_ntoa( addr.sin_addr ) );
up++; } fd_close(fd); f_aggregate_mapping(up*2); }
/ Martin Nilsson (DivX Networks)
returning mapping(string:mapping(string:mixed)) is probaby better. Then every interface could have ipv4, ipv6, mac and whatever else is interesting. I'll wait and see if someone with more configure-skillz implements this first before I check anything in...
/ Martin Nilsson (DivX Networks)
Previous text:
2004-09-11 11:40: Subject: gethostip
How portable is SIOCGIFCONF? Solaris 9 seems to consider it obsolete, and provides SIOCGLIFCONF as a replacement. And for W*ndows something else completely is probably needed.
Otherwise it seems ok, but it should of course return IPV6 addresses as well. Which makes the proposed API a bit awkward, since each interface may have two addresses, one V4 and one V6.
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
Well, the downside of that approach is that you need to always use x->ipv4 || x->ipv6 to be sure to get a valid address. Besides, Linux can assign several IPV6 addresses to the same interface (while Solaris instead creates a pseudo-interface for each additional address). Normally you have three V6 addresses for each interface, one link-local, one site-local and one global.
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
Previous text:
2004-09-11 13:29: Subject: gethostip
returning mapping(string:mapping(string:mixed)) is probaby better. Then every interface could have ipv4, ipv6, mac and whatever else is interesting. I'll wait and see if someone with more configure-skillz implements this first before I check anything in...
/ Martin Nilsson (DivX Networks)
Well, x->ip could always be one address and x->ipv6 could always be an array.
/ Martin Nilsson (DivX Networks)
Previous text:
2004-09-11 23:31: Subject: gethostip
Well, the downside of that approach is that you need to always use x->ipv4 || x->ipv6 to be sure to get a valid address. Besides, Linux can assign several IPV6 addresses to the same interface (while Solaris instead creates a pseudo-interface for each additional address). Normally you have three V6 addresses for each interface, one link-local, one site-local and one global.
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
Still, it seems a bit awkward to always have to do ({x->ipv4})+x->ipv6, why not just put all of them in an array?
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
Previous text:
2004-09-11 23:39: Subject: gethostip
Well, x->ip could always be one address and x->ipv6 could always be an array.
/ Martin Nilsson (DivX Networks)
Yes. Then for netmasks I suppose another array which matches positionally can be used (to loop over both, use Array.sum_arrays). I'm not sure what wold be the best way to represent a v6 netmask though. A string on the format "/64" perhaps?
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
Previous text:
2004-09-11 23:57: Subject: gethostip
..and name it x->ips
/ Martin Nilsson (DivX Networks)
i guess you want all of that: one that is guaranteed to always give you just one ip, one ip4 ip, all ip4 ips. one ip6 all ip6 all ips.
greetings, martin.
one that is guaranteed to always give you just one ip,
x->ips[0]
one ip4 ip,
filter(x->ips, lambda(string x) { return has_value(x, "."); })[0]
all ip4 ips.
filter(x->ips, lambda(string x) { return has_value(x, "."); })
one ip6
filter(x->ips, lambda(string x) { return has_value(x, ":"); })[0]
all ip6
filter(x->ips, lambda(string x) { return has_value(x, ":"); })
all ips.
x->ips
Since you normally don't need to differentiate between v4 and v6, it's acceptable that you need to do slightly more work in the cases where you do.
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
Previous text:
2004-09-12 00:06: Subject: Re: gethostip
i guess you want all of that: one that is guaranteed to always give you just one ip, one ip4 ip, all ip4 ips. one ip6 all ip6 all ips.
greetings, martin.
/ Brevbäraren
You can even skip the lambdas; filter(x->ips, has_value, ".")[0] et c.
/ Johan Sundström (Achtung Liebe!)
Previous text:
2004-09-12 00:11: Subject: Re: gethostip
one that is guaranteed to always give you just one ip,
x->ips[0]
one ip4 ip,
filter(x->ips, lambda(string x) { return has_value(x, "."); })[0]
all ip4 ips.
filter(x->ips, lambda(string x) { return has_value(x, "."); })
one ip6
filter(x->ips, lambda(string x) { return has_value(x, ":"); })[0]
all ip6
filter(x->ips, lambda(string x) { return has_value(x, ":"); })
all ips.
x->ips
Since you normally don't need to differentiate between v4 and v6, it's acceptable that you need to do slightly more work in the cases where you do.
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
pike-devel@lists.lysator.liu.se