2 * Copyright (C) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>
3 * Helsinki University of Technology, Finland.
5 * Copyright (C) 2005 Neil Cafferkey
6 * Copyright (C) 2005 Pavel Fedin
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
26 #include <aros/libcall.h>
28 #include <sys/param.h>
29 #include <sys/systm.h>
31 #include <sys/types.h>
32 #include <sys/socket.h>
33 #include <netinet/in.h>
36 #include <kern/amiga_includes.h>
38 #include <api/amiga_api.h>
39 #include <api/amiga_libcallentry.h>
40 #include <kern/amiga_netdb.h>
41 #include <api/allocdatabuffer.h>
43 #include <api/gethtbynamadr.h> /* prototypes (NO MORE BUGS HERE) */
45 int strcasecmp(const char *, const char *);
48 #define strcasecmp stricmp
52 static long copyGenent(struct SocketBase
* libPtr
,
53 struct DataBuffer
* DB
,
54 struct GenentNode
*ent
)
58 if (allocDataBuffer(DB
, ent
->gn_EntSize
) == FALSE
) {
59 writeErrnoValue(libPtr
, ENOMEM
);
64 * how much to add to old pointers
66 diff
= (caddr_t
)DB
->db_Addr
- (caddr_t
)&ent
->gn_Ent
;
69 * copy given ent verbatim
71 bcopy((caddr_t
)&ent
->gn_Ent
, DB
->db_Addr
, ent
->gn_EntSize
);
78 * Host queries if Nameserver is not in use *****************************
82 * Match name in aliaslist, used by `...byname()' -queries
85 static BOOL
matchAlias(char ** aliases
, const char * name
)
87 for ( ; *aliases
!= 0; aliases
++)
88 if (strcasecmp(*aliases
, name
) == 0)
96 * Makehostent() must be called when NDB_Semaphore is obtained.
98 static struct hostent
* makehostent(struct SocketBase
* libPtr
,
99 struct HostentNode
* ent
)
104 if ((diff
= copyGenent(libPtr
, &libPtr
->hostents
,
105 (struct GenentNode
*)ent
)) == 0)
106 return NULL
; /* failed to allocate memory */
111 #define HOSTENT ((struct hostent *)libPtr->hostents.db_Addr)
112 HOSTENT
->h_name
+= diff
;
114 HOSTENT
->h_aliases
= (char **)((caddr_t
)HOSTENT
->h_aliases
+ diff
);
115 for (i
= 0; HOSTENT
->h_aliases
[i
]; i
++)
116 HOSTENT
->h_aliases
[i
] += diff
;
117 /* NULL remains null */
119 HOSTENT
->h_addr_list
= (char **)((caddr_t
)HOSTENT
->h_addr_list
+ diff
);
120 for (i
= 0; HOSTENT
->h_addr_list
[i
]; i
++)
121 HOSTENT
->h_addr_list
[i
] += diff
;
122 /* NULL remains null */
129 struct hostent
* _gethtbyname(struct SocketBase
* libPtr
,
132 struct HostentNode
* entNode
;
133 struct hostent
* host
;
137 for (entNode
= (struct HostentNode
*)NDB
->ndb_Hosts
.mlh_Head
;
138 entNode
->hn_Node
.mln_Succ
;
139 entNode
= (struct HostentNode
*)entNode
->hn_Node
.mln_Succ
)
140 if (strcasecmp(entNode
->hn_Ent
.h_name
, (char *)name
) == 0 ||
141 matchAlias(entNode
->hn_Ent
.h_aliases
, name
)) {
142 host
= makehostent(libPtr
, entNode
);
147 writeErrnoValue(libPtr
, 0);
152 struct hostent
* _gethtbyaddr(struct SocketBase
* libPtr
,
153 const char * addr
, int len
, int type
)
155 struct HostentNode
* entNode
;
156 struct hostent
* host
;
159 for (entNode
= (struct HostentNode
*)NDB
->ndb_Hosts
.mlh_Head
;
160 entNode
->hn_Node
.mln_Succ
;
161 entNode
= (struct HostentNode
*)entNode
->hn_Node
.mln_Succ
)
162 if (entNode
->hn_Ent
.h_addrtype
== type
&&
163 ! bcmp(entNode
->hn_Ent
.h_addr
, addr
, len
)) {
164 host
= makehostent(libPtr
, entNode
);
169 writeErrnoValue(libPtr
, 0);
175 * Network queries ****************************************************
180 * Makenetent() must be called when NDB_Semaphore is obtained.
182 static struct netent
* makenetent(struct SocketBase
* libPtr
,
183 struct NetentNode
* ent
)
188 if ((diff
= copyGenent(libPtr
, &libPtr
->netents
,
189 (struct GenentNode
*)ent
)) == 0)
195 #define NETENT ((struct netent *)libPtr->netents.db_Addr)
196 NETENT
->n_name
+= diff
;
198 NETENT
->n_aliases
= (char **)((caddr_t
)NETENT
->n_aliases
+ diff
);
199 for (i
= 0; NETENT
->n_aliases
[i
]; i
++)
200 NETENT
->n_aliases
[i
] += diff
;
201 /* NULL remains null */
208 /*struct netent * SAVEDS getnetbyname(
209 REG(a0, const char * name),
210 REG(a6, struct SocketBase * libPtr))*/
211 AROS_LH1(struct netent
*, getnetbyname
,
212 AROS_LHA(const char *, name
, A0
),
213 struct SocketBase
*, libPtr
, 37, UL
)
216 struct NetentNode
* entNode
;
222 for (entNode
= (struct NetentNode
*)NDB
->ndb_Networks
.mlh_Head
;
223 entNode
->nn_Node
.mln_Succ
;
224 entNode
= (struct NetentNode
*)entNode
->nn_Node
.mln_Succ
)
225 if (strcmp(entNode
->nn_Ent
.n_name
, name
) == 0 ||
226 matchAlias(entNode
->nn_Ent
.n_aliases
, name
)) {
227 net
= makenetent(libPtr
, entNode
);
232 writeErrnoValue(libPtr
, 0);
237 /*struct netent * SAVEDS getnetbyaddr(
240 REG(a6, struct SocketBase * libPtr))*/
241 AROS_LH2(struct netent
*, getnetbyaddr
,
242 AROS_LHA(long, netw
, D0
),
243 AROS_LHA(long, type
, D1
),
244 struct SocketBase
*, libPtr
, 38, UL
)
247 struct NetentNode
* entNode
;
253 for (entNode
= (struct NetentNode
*)NDB
->ndb_Networks
.mlh_Head
;
254 entNode
->nn_Node
.mln_Succ
;
255 entNode
= (struct NetentNode
*)entNode
->nn_Node
.mln_Succ
)
256 if (entNode
->nn_Ent
.n_addrtype
== type
&& entNode
->nn_Ent
.n_net
== netw
) {
257 net
= makenetent(libPtr
, entNode
);
262 writeErrnoValue(libPtr
, 0);
269 * Service queries ****************************************************
273 * Makeservent() must be called when NDB_Semaphore is obtained.
275 static struct servent
* makeservent(struct SocketBase
* libPtr
,
276 struct ServentNode
* ent
)
281 if ((diff
= copyGenent(libPtr
, &libPtr
->servents
,
282 (struct GenentNode
*)ent
)) == 0)
288 #define SERVENT ((struct servent *)libPtr->servents.db_Addr)
289 SERVENT
->s_name
+= diff
;
291 SERVENT
->s_aliases
= (char **)((caddr_t
)SERVENT
->s_aliases
+ diff
);
292 for (i
= 0; SERVENT
->s_aliases
[i
]; i
++)
293 SERVENT
->s_aliases
[i
] += diff
;
294 /* NULL remains null */
296 SERVENT
->s_proto
+= diff
;
304 * findservent is needed for external call.
306 struct ServentNode
* findServentNode(struct NetDataBase
* ndb
,
307 const char * name
, const char * proto
)
309 struct ServentNode
* entNode
;
311 for (entNode
= (struct ServentNode
*)ndb
->ndb_Services
.mlh_Head
;
312 entNode
->sn_Node
.mln_Succ
;
313 entNode
= (struct ServentNode
*)entNode
->sn_Node
.mln_Succ
)
314 if ((strcmp(entNode
->sn_Ent
.s_name
, name
) == 0 ||
315 matchAlias(entNode
->sn_Ent
.s_aliases
, name
)) &&
316 (proto
== NULL
|| strcmp(entNode
->sn_Ent
.s_proto
, proto
) == 0))
324 /*struct servent * SAVEDS getservbyname(
325 REG(a0, const char * name),
326 REG(a1, const char * proto),
327 REG(a6, struct SocketBase * libPtr))*/
328 AROS_LH2(struct servent
*, getservbyname
,
329 AROS_LHA(const char *, name
, A0
),
330 AROS_LHA(const char *, proto
, A1
),
331 struct SocketBase
*, libPtr
, 39, UL
)
334 struct ServentNode
* entNode
;
335 struct servent
* serv
;
340 if ((entNode
= findServentNode(NDB
, name
, proto
)) != NULL
) {
341 serv
= makeservent(libPtr
, entNode
);
346 writeErrnoValue(libPtr
, 0);
351 /*struct servent * SAVEDS getservbyport(
353 REG(a0, const char * proto),
354 REG(a6, struct SocketBase * libPtr))*/
355 AROS_LH2(struct servent
*, getservbyport
,
356 AROS_LHA(LONG
, port
, D0
),
357 AROS_LHA(const char *, proto
, A0
),
358 struct SocketBase
*, libPtr
, 40, UL
)
361 struct ServentNode
* entNode
;
362 struct servent
* serv
;
367 for (entNode
= (struct ServentNode
*)NDB
->ndb_Services
.mlh_Head
;
368 entNode
->sn_Node
.mln_Succ
;
369 entNode
= (struct ServentNode
*)entNode
->sn_Node
.mln_Succ
)
370 if (entNode
->sn_Ent
.s_port
== port
&&
371 (proto
== NULL
|| strcmp(entNode
->sn_Ent
.s_proto
, proto
) == 0)) {
372 serv
= makeservent(libPtr
, entNode
);
378 writeErrnoValue(libPtr
, 0);
385 * Protocol queries ****************************************************
389 * Makeprotoent() must be called when NDB_Semaphore is obtained.
391 static struct protoent
* makeprotoent(struct SocketBase
* libPtr
,
392 struct ProtoentNode
* ent
)
397 if ((diff
= copyGenent(libPtr
, &libPtr
->protoents
,
398 (struct GenentNode
*)ent
)) == 0)
404 #define PROTOENT ((struct protoent *)libPtr->protoents.db_Addr)
405 PROTOENT
->p_name
+= diff
;
407 PROTOENT
->p_aliases
= (char **)((caddr_t
)PROTOENT
->p_aliases
+ diff
);
408 for (i
= 0; PROTOENT
->p_aliases
[i
]; i
++)
409 PROTOENT
->p_aliases
[i
] += diff
;
410 /* NULL remains null */
416 /*struct protoent * SAVEDS getprotobyname(
417 REG(a0, const char * name),
418 REG(a6, struct SocketBase * libPtr))*/
419 AROS_LH1(struct protoent
*, getprotobyname
,
420 AROS_LHA(const char *, name
, A0
),
421 struct SocketBase
*, libPtr
, 41, UL
)
424 struct ProtoentNode
* entNode
;
425 struct protoent
* proto
;
430 for (entNode
= (struct ProtoentNode
*)NDB
->ndb_Protocols
.mlh_Head
;
431 entNode
->pn_Node
.mln_Succ
;
432 entNode
= (struct ProtoentNode
*)entNode
->pn_Node
.mln_Succ
)
433 if (strcmp(entNode
->pn_Ent
.p_name
, name
) == 0 ||
434 matchAlias(entNode
->pn_Ent
.p_aliases
, name
)) {
435 proto
= makeprotoent(libPtr
, entNode
);
440 writeErrnoValue(libPtr
, 0);
445 /*struct protoent * SAVEDS getprotobynumber(
446 REG(a0, long protoc),
447 REG(a6, struct SocketBase * libPtr))*/
448 AROS_LH1(struct protoent
*, getprotobynumber
,
449 AROS_LHA(long, protoc
, A0
),
450 struct SocketBase
*, libPtr
, 42, UL
)
453 struct ProtoentNode
* entNode
;
454 struct protoent
* proto
;
459 for (entNode
= (struct ProtoentNode
*)NDB
->ndb_Protocols
.mlh_Head
;
460 entNode
->pn_Node
.mln_Succ
;
461 entNode
= (struct ProtoentNode
*)entNode
->pn_Node
.mln_Succ
)
462 if (entNode
->pn_Ent
.p_proto
== protoc
) {
463 proto
= makeprotoent(libPtr
, entNode
);
469 writeErrnoValue(libPtr
, 0);