]>
git.saurik.com Git - apt.git/blob - methods/rfc2553emu.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: rfc2553emu.cc,v 1.8 2001/02/20 07:03:18 jgg Exp $
4 /* ######################################################################
6 RFC 2553 Emulation - Provides emulation for RFC 2553 getaddrinfo,
7 freeaddrinfo and getnameinfo
9 This is really C code, it just has a .cc extensions to play nicer with
12 Originally written by Jason Gunthorpe <jgg@debian.org> and placed into
13 the Public Domain, do with it what you will.
15 ##################################################################### */
20 #include <arpa/inet.h>
21 #include <netinet/in.h>
24 #include "rfc2553emu.h"
26 #ifndef HAVE_GETADDRINFO
27 // getaddrinfo - Resolve a hostname /*{{{*/
28 // ---------------------------------------------------------------------
30 int getaddrinfo(const char *nodename
, const char *servname
,
31 const struct addrinfo
*hints
,
32 struct addrinfo
**res
)
34 struct addrinfo
**Result
= res
;
41 // Try to convert the service as a number
42 Port
= htons(strtol(servname
,(char **)&End
,0));
45 if (hints
!= 0 && hints
->ai_socktype
!= 0)
46 Proto
= hints
->ai_socktype
;
48 // Not a number, must be a name.
49 if (End
!= servname
+ strlen(servname
))
51 struct servent
*Srv
= 0;
53 // Do a lookup in the service database
54 if (hints
== 0 || hints
->ai_socktype
== SOCK_STREAM
)
55 Srv
= getservbyname(servname
,"tcp");
56 if (hints
!= 0 && hints
->ai_socktype
== SOCK_DGRAM
)
57 Srv
= getservbyname(servname
,"udp");
61 // Get the right protocol
63 if (strcmp(Srv
->s_proto
,"tcp") == 0)
67 if (strcmp(Srv
->s_proto
,"udp") == 0)
73 if (hints
!= 0 && hints
->ai_socktype
!= Proto
&&
74 hints
->ai_socktype
!= 0)
78 // Hostname lookup, only if this is not a listening socket
79 if (hints
!= 0 && (hints
->ai_flags
& AI_PASSIVE
) != AI_PASSIVE
)
81 Addr
= gethostbyname(nodename
);
84 if (h_errno
== TRY_AGAIN
)
86 if (h_errno
== NO_RECOVERY
)
92 if (Addr
->h_addr_list
[0] == 0)
95 CurAddr
= Addr
->h_addr_list
;
98 CurAddr
= (char **)&End
; // Fake!
100 // Start constructing the linked list
102 for (; *CurAddr
!= 0; CurAddr
++)
104 // New result structure
105 *Result
= (struct addrinfo
*)calloc(sizeof(**Result
),1);
114 (*Result
)->ai_family
= AF_INET
;
115 (*Result
)->ai_socktype
= Proto
;
117 // If we have the IPPROTO defines we can set the protocol field
119 if (Proto
== SOCK_STREAM
)
120 (*Result
)->ai_protocol
= IPPROTO_TCP
;
121 if (Proto
== SOCK_DGRAM
)
122 (*Result
)->ai_protocol
= IPPROTO_UDP
;
125 // Allocate space for the address
126 (*Result
)->ai_addrlen
= sizeof(struct sockaddr_in
);
127 (*Result
)->ai_addr
= (struct sockaddr
*)calloc(sizeof(sockaddr_in
),1);
128 if ((*Result
)->ai_addr
== 0)
135 ((struct sockaddr_in
*)(*Result
)->ai_addr
)->sin_family
= AF_INET
;
136 ((struct sockaddr_in
*)(*Result
)->ai_addr
)->sin_port
= Port
;
138 if (hints
!= 0 && (hints
->ai_flags
& AI_PASSIVE
) != AI_PASSIVE
)
139 ((struct sockaddr_in
*)(*Result
)->ai_addr
)->sin_addr
= *(in_addr
*)(*CurAddr
);
142 // Already zerod by calloc.
146 Result
= &(*Result
)->ai_next
;
152 // freeaddrinfo - Free the result of getaddrinfo /*{{{*/
153 // ---------------------------------------------------------------------
155 void freeaddrinfo(struct addrinfo
*ai
)
165 #endif // HAVE_GETADDRINFO
167 #ifndef HAVE_GETNAMEINFO
168 // getnameinfo - Convert a sockaddr to a string /*{{{*/
169 // ---------------------------------------------------------------------
171 int getnameinfo(const struct sockaddr
*sa
, socklen_t salen
,
172 char *host
, size_t hostlen
,
173 char *serv
, size_t servlen
,
176 struct sockaddr_in
*sin
= (struct sockaddr_in
*)sa
;
178 // This routine only supports internet addresses
179 if (sa
->sa_family
!= AF_INET
)
180 return EAI_ADDRFAMILY
;
184 // Try to resolve the hostname
185 if ((flags
& NI_NUMERICHOST
) != NI_NUMERICHOST
)
187 struct hostent
*Ent
= gethostbyaddr((char *)&sin
->sin_addr
,sizeof(sin
->sin_addr
),
190 strncpy(host
,Ent
->h_name
,hostlen
);
193 if ((flags
& NI_NAMEREQD
) == NI_NAMEREQD
)
195 if (h_errno
== TRY_AGAIN
)
197 if (h_errno
== NO_RECOVERY
)
202 flags
|= NI_NUMERICHOST
;
206 // Resolve as a plain numberic
207 if ((flags
& NI_NUMERICHOST
) == NI_NUMERICHOST
)
209 strncpy(host
,inet_ntoa(sin
->sin_addr
),hostlen
);
215 // Try to resolve the hostname
216 if ((flags
& NI_NUMERICSERV
) != NI_NUMERICSERV
)
219 if ((flags
& NI_DATAGRAM
) == NI_DATAGRAM
)
220 Ent
= getservbyport(ntohs(sin
->sin_port
),"udp");
222 Ent
= getservbyport(ntohs(sin
->sin_port
),"tcp");
225 strncpy(serv
,Ent
->s_name
,servlen
);
228 if ((flags
& NI_NAMEREQD
) == NI_NAMEREQD
)
231 flags
|= NI_NUMERICSERV
;
235 // Resolve as a plain numberic
236 if ((flags
& NI_NUMERICSERV
) == NI_NUMERICSERV
)
238 snprintf(serv
,servlen
,"%u",ntohs(sin
->sin_port
));
245 #endif // HAVE_GETNAMEINFO