PageRenderTime 38ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/dnssec-tools-1.13/tools/modules/Net-addrinfo/addrinfo.pm

#
Perl | 297 lines | 207 code | 70 blank | 20 comment | 26 complexity | 69ac09b8bf40ce22f415c8921271f5c6 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. #
  2. # addrinfo.pm -- Perl 5 interface to getaddrinfo(3) and related structs
  3. #
  4. # written by G. S. Marzot (marz@users.sourceforge.net)
  5. #
  6. # Copyright (c) 2006-2009 G. S. Marzot. All rights reserved.
  7. #
  8. # Copyright (c) 2006-2012 SPARTA, Inc. All rights reserved.
  9. #
  10. # This program is free software; you can redistribute it and/or
  11. # modify it under the same terms as Perl itself.
  12. #
  13. package Net::addrinfo;
  14. use Socket qw(:all);
  15. use Carp;
  16. our $VERSION = '1.02'; # current release version number
  17. use Exporter;
  18. use DynaLoader;
  19. sub AUTOLOAD {
  20. my $sub = $AUTOLOAD;
  21. (my $constname = $sub) =~ s/.*:://;
  22. my $val = (exists $LOCAL_CONSTANTS{$constname} ?
  23. $LOCAL_CONSTANTS{$constname} : constant($constname));
  24. if (not defined $val) {
  25. croak "Your vendor has not defined constant $constname";
  26. }
  27. *$sub = sub { $val }; # same as: eval "sub $sub { $val }";
  28. goto &$sub;
  29. }
  30. our @ISA = qw(Exporter DynaLoader);
  31. # our @EXPORT = qw( getaddrinfo );
  32. our @AI_FLAGS = qw(AI_NUMERICHOST AI_NUMERICSERV AI_PASSIVE AI_V4MAPPED AI_ADDRCONFIG AI_ALL AI_CANONIDN AI_CANONNAME AI_IDN AI_IDN_ALLOW_UNASSIGNED AI_IDN_USE_STD3_ASCII_RULES);
  33. #hack to make up for missing constants - should be provided with 'Socket'
  34. our %LOCAL_CONSTANTS = qw(IPPROTO_IP 0 IPPROTO_HOPOPTS 0 IPPROTO_ICMP 1 IPPROTO_IGMP 2 IPPROTO_IPIP 4 IPPROTO_EGP 8 IPPROTO_PUP 12 IPPROTO_UDP 17 IPPROTO_IDP 22 IPPROTO_TP 29 IPPROTO_IPV6 41 IPPROTO_ROUTING 43 IPPROTO_FRAGMENT 44 IPPROTO_RSVP 46 IPPROTO_GRE 47 IPPROTO_ESP 50 IPPROTO_AH 51 IPPROTO_ICMPV6 58 IPPROTO_NONE 59 IPPROTO_RAW 255 IPPROTO_DSTOPTS 60 IPPROTO_MTP 92 IPPROTO_ENCAP 98 IPPROTO_PIM 103 IPPROTO_COMP 108 IPPROTO_SCTP 132);
  35. our @EXPORT = qw(getaddrinfo gai_strerror AI_ADDRCONFIG AI_ALL AI_CANONIDN AI_CANONNAME AI_IDN AI_IDN_ALLOW_UNASSIGNED AI_IDN_USE_STD3_ASCII_RULES AI_NUMERICHOST AI_NUMERICSERV AI_PASSIVE AI_V4MAPPED EAI_ADDRFAMILY EAI_AGAIN EAI_ALLDONE EAI_BADFLAGS EAI_CANCELED EAI_FAIL EAI_FAMILY EAI_IDN_ENCODE EAI_INPROGRESS EAI_INTR EAI_MEMORY EAI_NODATA EAI_NONAME EAI_NOTCANCELED EAI_OVERFLOW EAI_SERVICE EAI_SOCKTYPE EAI_BADHINTS EAI_SYSTEM GAI_NOWAIT GAI_WAIT NI_DGRAM NI_IDN NI_IDN_ALLOW_UNASSIGNED NI_IDN_USE_STD3_ASCII_RULES NI_MAXHOST NI_MAXSERV NI_NAMEREQD NI_NOFQDN NI_NUMERICHOST NI_NUMERICSERV IPPROTO_IP IPPROTO_HOPOPTS IPPROTO_ICMP IPPROTO_IGMP IPPROTO_IPIP IPPROTO_EGP IPPROTO_PUP IPPROTO_UDP IPPROTO_IDP IPPROTO_TP IPPROTO_IPV6 IPPROTO_ROUTING IPPROTO_FRAGMENT IPPROTO_RSVP IPPROTO_GRE IPPROTO_ESP IPPROTO_AH IPPROTO_ICMPV6 IPPROTO_NONE IPPROTO_RAW IPPROTO_DSTOPTS IPPROTO_MTP IPPROTO_ENCAP IPPROTO_PIM IPPROTO_COMP IPPROTO_SCTP);
  36. bootstrap Net::addrinfo;
  37. sub new {
  38. my $type = shift;
  39. my $self = {flags=>0, family=>0, socktype=>0, protocol=>0, addrlen=>0,
  40. addr=>undef, cannonname=>undef};
  41. my %params = @_;
  42. @$self{keys %params} = values %params;
  43. bless $self, $type;
  44. }
  45. sub flags {
  46. my $self = shift;
  47. if (@_) {
  48. $self->{flags} = scalar(shift);
  49. }
  50. return $self->{flags};
  51. }
  52. sub family {
  53. my $self = shift;
  54. if (@_) {
  55. $self->{family} = int(shift);
  56. }
  57. return $self->{family};
  58. }
  59. sub socktype {
  60. my $self = shift;
  61. if (@_) {
  62. $self->{socktype} = int(shift);
  63. }
  64. return $self->{socktype};
  65. }
  66. sub protocol {
  67. my $self = shift;
  68. if (@_) {
  69. $self->{protocol} = int(shift);
  70. }
  71. return $self->{protocol};
  72. }
  73. sub addrlen {
  74. my $self = shift;
  75. if (@_) {
  76. $self->{addrlen} = int(shift);
  77. }
  78. return $self->{addrlen};
  79. }
  80. sub addr {
  81. my $self = shift;
  82. if (@_) {
  83. $self->{addr} = scalar(shift);
  84. }
  85. return $self->{addr};
  86. }
  87. sub canonname {
  88. my $self = shift;
  89. if (@_) {
  90. $self->{canonname} = scalar(shift);
  91. }
  92. return $self->{canonname};
  93. }
  94. # special accessor sub for val_addrinfo structures in support of DNSSEC
  95. # note: not present ot relevant for non-DNSSEC applications
  96. sub val_status {
  97. my $self = shift;
  98. if (@_) {
  99. $self->{val_status} = scalar(shift);
  100. }
  101. return $self->{val_status};
  102. }
  103. sub stringify {
  104. my $self = shift;
  105. my $dstr;
  106. $dstr .= "{\n";
  107. my $flags = join('|',grep {$self->flags & eval("\&$_;");}@AI_FLAGS);
  108. $dstr .= "\tai_flags = ($flags)\n";
  109. my $family = $self->family;
  110. $family = (($family == AF_UNSPEC) ? "AF_UNSPEC" :
  111. (($family == AF_INET) ? "AF_INET" :
  112. (($family == AF_INET6) ? "AF_INET6" : "Unknown")));
  113. $dstr .= "\tai_family = $family\n";
  114. my $socktype = $self->socktype;
  115. $socktype = (($socktype == SOCK_STREAM) ? "SOCK_STREAM" :
  116. (($socktype == SOCK_DGRAM) ? "SOCK_DGRAM" :
  117. (($socktype == SOCK_RAW) ? "SOCK_RAW" : "Unknown")));
  118. $dstr .= "\tai_socktype = $socktype\n";
  119. my $protocol = $self->protocol;
  120. $protocol = (($protocol == IPPROTO_UDP()) ? "IPPROTO_UDP" :
  121. (($protocol == IPPROTO_TCP) ? "IPPROTO_TCP" :
  122. (($protocol == IPPROTO_IP()) ? "IPPROTO_IP" : "Unknown")));
  123. $dstr .= "\tai_protocol = $protocol\n";
  124. my $addrlen = $self->addrlen || length($self->addr);
  125. $dstr .= "\tai_addrlen = $addrlen\n";
  126. my $addr;
  127. if ($self->addr) {
  128. if ($self->family == AF_INET) {
  129. my ($port,$iaddr) = unpack_sockaddr_in($self->addr);
  130. $addr = "($port, " . inet_ntoa($iaddr) . ")";
  131. # } elsif ($self->family == AF_INET6) {
  132. #
  133. # XXX needs implementation
  134. } else {
  135. $addr = "0x" . unpack("H*",$self->addr);
  136. }
  137. }
  138. $dstr .= "\tai_addr = $addr\n";
  139. my $canonname = (defined $self->canonname ? $self->canonname : "<undef>");
  140. $dstr .= "\tai_canonname = $canonname\n";
  141. if (exists $self->{val_status}) {
  142. my $val_status = $self->val_status;
  143. $dstr .= "\tai_val_status = $val_status\n";
  144. }
  145. $dstr .= "}\n";
  146. return $dstr;
  147. }
  148. sub getaddrinfo {
  149. my $node = shift;
  150. my $service = shift;
  151. my $hints = shift;
  152. my $result = Net::addrinfo::_getaddrinfo($node, $service, $hints);
  153. $result = [$result] unless ref $result eq 'ARRAY';
  154. return (wantarray ? @$result : shift(@$result));
  155. }
  156. sub gai_strerror {
  157. my $errstr = Net::addrinfo::_gai_strerror(@_);
  158. return $errstr;
  159. }
  160. sub DESTROY {
  161. # print STDERR "addrinfo:DESTROY\n";
  162. }
  163. 1;
  164. __END__
  165. =head1 NAME
  166. Net::addrinfo - interface to POSIX getaddrinfo(3) and related
  167. constants, structures and functions.
  168. =head1 SYNOPSIS
  169. use Net::addrinfo;
  170. my $ainfo = getaddrinfo("www.marzot.net");
  171. =head1 DESCRIPTION
  172. This Perl module is designed to implement and export functionality
  173. related to the POSIX getaddrinfo(3) system call. The Net::addrinfo
  174. data object is provided with field name accsessor functions, similarly
  175. named to the the C data structure definition in F<netdb.h>. The
  176. getaddrinfo(3), gai_strerror(3) calls, and related constants are
  177. exported.
  178. The getaddrinfo() routine mimics the POSIX documented funtion (see
  179. system man page getaddrinfo(3)).
  180. On success the getaddrinfo() will return an array of Net::addrinfo
  181. data objects.
  182. In scalar context getaddrinfo() will return the first element from the
  183. Net::addrinfo array.
  184. In case of error, a numeric error code is returned.
  185. The error code may be passed to gai_strerror() to get a string
  186. representation of the error.
  187. New Net::addrinfo objects may be created with the package constructor
  188. and any number (or none) of the fields may be specified.
  189. flags => scalar integer
  190. family => scalar integer (e.g., AF_INET,m AF_INET6, etc.)
  191. socktype => scalar integer (e.g., SOCK_DGRAM, SOCK_STREAM, etc.)
  192. protocol => scalar integer (e.g., IPPROTO_UDP, IPPROTO_TCP, etc.)
  193. addrlen => scalar integer (can be computed by length($self->addr))
  194. addr => packed bytes (e.g., $self->addr(inet_aton("192.168.1.1")); )
  195. Flags may be set in the structure so that it may be used as a 'hint'
  196. parameter to the getaddrinfo() function. See exported @AI_FLAGS for
  197. list of acceptable constants.
  198. (Note: a special scalar integer field, 'val_status', is provided in
  199. support of DNSSEC aware addrinfo results (see Net::DNS::SEC::Validator))
  200. =head1 EXAMPLES
  201. use Net::addrinfo;
  202. use Socket qw(:all);
  203. my $hint = new Net::addrinfo(flags => AI_CANONNAME,
  204. family => AF_INET,
  205. socktype => SOCK_DGRAM);
  206. my (@ainfo) = getaddrinfo("www.marzot.net", "http", $hint);
  207. foreach $ainfo (@ainfo) {
  208. if (ref $ainfo eq 'Net::addrinfo') {
  209. print $ainfo->stringify(), "\n";
  210. print "addr = ", inet_ntoa($ainfo->addr), "\n";
  211. ...
  212. connect(SH, $ainfo->addr);
  213. } else {
  214. print "Error($ainfo):", gai_strerror($ainfo), "\n";
  215. }
  216. }
  217. =head1 NOTE
  218. One should not rely on the internal representation of this class.
  219. =head1 AUTHOR
  220. G. S. Marzot (marz@users.sourceforge.net)
  221. =head1 COPYRIGHT AND LICENSE
  222. Copyright (c) 2006 G. S. Marzot. All rights reserved. This program
  223. is free software; you can redistribute it and/or modify it under
  224. the same terms as Perl itself.
  225. Copyright (c) 2006-2008 SPARTA, Inc. All Rights Reserved. This program
  226. is free software; you can redistribute it and/or modify it under
  227. the same terms as Perl itself.