2 * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
27 * Copyright (C) 1989 by NeXT, Inc.
30 #include <mach/mach.h>
33 #include <rpc/types.h>
36 #include <sys/socket.h>
37 #include <netinet/in.h>
38 #include <arpa/inet.h>
41 #include "_lu_types.h"
45 static pthread_mutex_t _network_lock
= PTHREAD_MUTEX_INITIALIZER
;
51 extern struct netent
*_res_getnetbyaddr();
52 extern struct netent
*_res_getnetbyname();
53 extern struct netent
*_old_getnetbyaddr();
54 extern struct netent
*_old_getnetbyname();
55 extern struct netent
*_old_getnetent();
56 extern void _old_setnetent();
57 extern void _old_endnetent();
59 extern mach_port_t _lu_port
;
60 extern int _lu_running(void);
63 free_network_data(struct netent
*n
)
67 if (n
== NULL
) return;
71 aliases
= n
->n_aliases
;
74 while (*aliases
!= NULL
) free(*aliases
++);
80 free_network(struct netent
*n
)
82 if (n
== NULL
) return;
88 free_lu_thread_info_network(void *x
)
90 struct lu_thread_info
*tdata
;
92 if (x
== NULL
) return;
94 tdata
= (struct lu_thread_info
*)x
;
96 if (tdata
->lu_entry
!= NULL
)
98 free_network((struct netent
*)tdata
->lu_entry
);
99 tdata
->lu_entry
= NULL
;
102 _lu_data_free_vm_xdr(tdata
);
107 static struct netent
*
108 extract_network(XDR
*xdr
)
111 int i
, j
, nvals
, nkeys
, status
;
114 if (xdr
== NULL
) return NULL
;
116 if (!xdr_int(xdr
, &nkeys
)) return NULL
;
118 n
= (struct netent
*)calloc(1, sizeof(struct netent
));
120 n
->n_addrtype
= AF_INET
;
122 for (i
= 0; i
< nkeys
; i
++)
128 status
= _lu_xdr_attribute(xdr
, &key
, &vals
, &nvals
);
143 if ((n
->n_name
== NULL
) && (!strcmp("name", key
)))
148 n
->n_aliases
= (char **)calloc(nvals
, sizeof(char *));
149 for (j
= 1; j
< nvals
; j
++) n
->n_aliases
[j
-1] = vals
[j
];
153 else if (!strcmp("address", key
))
155 n
->n_net
= inet_network(vals
[0]);
161 for (; j
< nvals
; j
++) free(vals
[j
]);
166 if (n
->n_name
== NULL
) n
->n_name
= strdup("");
167 if (n
->n_aliases
== NULL
) n
->n_aliases
= (char **)calloc(1, sizeof(char *));
172 static struct netent
*
173 copy_network(struct netent
*in
)
178 if (in
== NULL
) return NULL
;
180 n
= (struct netent
*)calloc(1, sizeof(struct netent
));
182 n
->n_name
= LU_COPY_STRING(in
->n_name
);
185 if (in
->n_aliases
!= NULL
)
187 for (len
= 0; in
->n_aliases
[len
] != NULL
; len
++);
190 n
->n_aliases
= (char **)calloc(len
+ 1, sizeof(char *));
191 for (i
= 0; i
< len
; i
++)
193 n
->n_aliases
[i
] = strdup(in
->n_aliases
[i
]);
196 n
->n_addrtype
= in
->n_addrtype
;
197 n
->n_net
= in
->n_net
;
203 recycle_network(struct lu_thread_info
*tdata
, struct netent
*in
)
207 if (tdata
== NULL
) return;
208 n
= (struct netent
*)tdata
->lu_entry
;
213 tdata
->lu_entry
= NULL
;
216 if (tdata
->lu_entry
== NULL
)
218 tdata
->lu_entry
= in
;
222 free_network_data(n
);
224 n
->n_name
= in
->n_name
;
225 n
->n_aliases
= in
->n_aliases
;
226 n
->n_addrtype
= in
->n_addrtype
;
227 n
->n_net
= in
->n_net
;
232 static struct netent
*
233 lu_getnetbyaddr(long addr
, int type
)
238 static int proc
= -1;
242 if (type
!= AF_INET
) return NULL
;
246 if (_lookup_link(_lu_port
, "getnetbyaddr", &proc
) != KERN_SUCCESS
)
256 if (_lookup_all(_lu_port
, proc
, (unit
*)&addr
, 1, &lookup_buf
, &datalen
) != KERN_SUCCESS
)
261 datalen
*= BYTES_PER_XDR_UNIT
;
262 if ((lookup_buf
== NULL
) || (datalen
== 0)) return NULL
;
264 xdrmem_create(&inxdr
, lookup_buf
, datalen
, XDR_DECODE
);
267 if (!xdr_int(&inxdr
, &count
))
270 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
277 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
281 n
= extract_network(&inxdr
);
283 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
288 static struct netent
*
289 lu_getnetbyname(const char *name
)
293 char namebuf
[_LU_MAXLUSTRLEN
+ BYTES_PER_XDR_UNIT
];
296 static int proc
= -1;
302 if (_lookup_link(_lu_port
, "getnetbyname", &proc
) != KERN_SUCCESS
)
308 xdrmem_create(&outxdr
, namebuf
, sizeof(namebuf
), XDR_ENCODE
);
309 if (!xdr__lu_string(&outxdr
, (_lu_string
*)&name
))
311 xdr_destroy(&outxdr
);
318 if (_lookup_all(_lu_port
, proc
, (unit
*)namebuf
,
319 xdr_getpos(&outxdr
) / BYTES_PER_XDR_UNIT
, &lookup_buf
, &datalen
)
322 xdr_destroy(&outxdr
);
326 xdr_destroy(&outxdr
);
328 datalen
*= BYTES_PER_XDR_UNIT
;
329 if ((lookup_buf
== NULL
) || (datalen
== 0)) return NULL
;
331 xdrmem_create(&inxdr
, lookup_buf
, datalen
, XDR_DECODE
);
334 if (!xdr_int(&inxdr
, &count
))
337 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
344 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
348 n
= extract_network(&inxdr
);
350 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
358 struct lu_thread_info
*tdata
;
360 tdata
= _lu_data_create_key(_lu_data_key_network
, free_lu_thread_info_network
);
361 _lu_data_free_vm_xdr(tdata
);
370 static struct netent
*
373 static int proc
= -1;
374 struct lu_thread_info
*tdata
;
377 tdata
= _lu_data_create_key(_lu_data_key_network
, free_lu_thread_info_network
);
380 tdata
= (struct lu_thread_info
*)calloc(1, sizeof(struct lu_thread_info
));
381 _lu_data_set_key(_lu_data_key_network
, tdata
);
384 if (tdata
->lu_vm
== NULL
)
388 if (_lookup_link(_lu_port
, "getnetent", &proc
) != KERN_SUCCESS
)
395 if (_lookup_all(_lu_port
, proc
, NULL
, 0, &(tdata
->lu_vm
), &(tdata
->lu_vm_length
)) != KERN_SUCCESS
)
401 /* mig stubs measure size in words (4 bytes) */
402 tdata
->lu_vm_length
*= 4;
404 if (tdata
->lu_xdr
!= NULL
)
406 xdr_destroy(tdata
->lu_xdr
);
409 tdata
->lu_xdr
= (XDR
*)calloc(1, sizeof(XDR
));
411 xdrmem_create(tdata
->lu_xdr
, tdata
->lu_vm
, tdata
->lu_vm_length
, XDR_DECODE
);
412 if (!xdr_int(tdata
->lu_xdr
, &tdata
->lu_vm_cursor
))
419 if (tdata
->lu_vm_cursor
== 0)
425 n
= extract_network(tdata
->lu_xdr
);
432 tdata
->lu_vm_cursor
--;
437 static struct netent
*
438 getnet(const char *name
, long addr
, int type
, int source
)
440 struct netent
*res
= NULL
;
441 struct lu_thread_info
*tdata
;
443 tdata
= _lu_data_create_key(_lu_data_key_network
, free_lu_thread_info_network
);
446 tdata
= (struct lu_thread_info
*)calloc(1, sizeof(struct lu_thread_info
));
447 _lu_data_set_key(_lu_data_key_network
, tdata
);
455 res
= lu_getnetbyname(name
);
458 res
= lu_getnetbyaddr(addr
, type
);
461 res
= lu_getnetent();
468 pthread_mutex_lock(&_network_lock
);
472 res
= copy_network(_old_getnetbyname(name
));
475 res
= copy_network(_old_getnetbyaddr(addr
, type
));
478 res
= copy_network(_old_getnetent());
482 pthread_mutex_unlock(&_network_lock
);
485 recycle_network(tdata
, res
);
486 return (struct netent
*)tdata
->lu_entry
;
490 getnetbyaddr(long addr
, int type
)
492 return getnet(NULL
, addr
, type
, N_GET_ADDR
);
496 getnetbyname(const char *name
)
498 return getnet(name
, 0, 0, N_GET_NAME
);
504 return getnet(NULL
, 0, 0, N_GET_ENT
);
508 setnetent(int stayopen
)
510 if (_lu_running()) lu_setnetent();
511 else _old_setnetent(stayopen
);
517 if (_lu_running()) lu_endnetent();
518 else _old_endnetent();