2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.1 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
25 * Copyright (C) 1990 by NeXT, Inc. All rights reserved.
29 * ni_pwdomain function: present working domain for a netinfo handle
32 * ni_status ni_pwdomain(void *ni, ni_name *buf)
34 * pwd is returned in buf, which can be freed with ni_name_free
38 #include <sys/types.h>
39 #include <sys/param.h>
42 #include <netinfo/ni.h>
44 #include <sys/socket.h>
46 #include <sys/ioctl.h>
48 extern char *inet_ntoa();
50 static const char NAME_NAME
[] = "name";
51 static const char NAME_MACHINES
[] = "machines";
52 static const char NAME_IP_ADDRESS
[] = "ip_address";
53 static const char NAME_SERVES
[] = "serves";
54 static const char NAME_UNKNOWN
[] = "###UNKNOWN###";
62 struct in_addr netaddr
;
69 interface_t
*interface
;
72 static interface_list_t
*my_interfaces
= NULL
;
74 static interface_list_t
*
79 char buf
[1024]; /* XXX */
80 int offset
, addrlen
, extra
, delta
;
84 if (my_interfaces
!= NULL
) return my_interfaces
;
86 sock
= socket(AF_INET
, SOCK_DGRAM
, 0);
88 if (sock
< 0) return NULL
;
90 ifc
.ifc_len
= sizeof(buf
);
93 if (ioctl(sock
, SIOCGIFCONF
, (char *)&ifc
) < 0)
99 my_interfaces
= (interface_list_t
*)malloc(sizeof(interface_list_t
));
100 my_interfaces
->count
= 0;
101 my_interfaces
->interface
= NULL
;
103 delta
= sizeof(struct ifreq
);
104 addrlen
= delta
- IFNAMSIZ
;
109 while (offset
<= ifc
.ifc_len
)
111 ifr
= (struct ifreq
*)(ifc
.ifc_buf
+ offset
);
113 #ifndef _NO_SOCKADDR_LENGTH_
114 extra
= ifr
->ifr_addr
.sa_len
- addrlen
;
115 if (extra
< 0) extra
= 0;
118 offset
= offset
+ delta
+ extra
;
120 if (ifr
->ifr_addr
.sa_family
!= AF_INET
) continue;
121 if (ioctl(sock
, SIOCGIFFLAGS
, (char *)ifr
) < 0) continue;
123 my_interfaces
->count
++;
124 if (my_interfaces
->count
== 1)
126 my_interfaces
->interface
= (interface_t
*)malloc(sizeof(interface_t
));
130 my_interfaces
->interface
= (interface_t
*)realloc(my_interfaces
->interface
, my_interfaces
->count
* sizeof(interface_t
));
133 iface
= &(my_interfaces
->interface
[my_interfaces
->count
- 1]);
134 memset(iface
, 0, sizeof(interface_t
));
136 memmove(iface
->name
, ifr
->ifr_name
, IFNAMSIZ
);
137 iface
->flags
= ifr
->ifr_ifru
.ifru_flags
;
138 iface
->addr
.s_addr
= ((struct sockaddr_in
*)&(ifr
->ifr_addr
))->sin_addr
.s_addr
;
139 ioctl(sock
, SIOCGIFNETMASK
, (char *)ifr
);
140 iface
->mask
.s_addr
= ((struct sockaddr_in
*)&(ifr
->ifr_addr
))->sin_addr
.s_addr
;
141 iface
->netaddr
.s_addr
= iface
->addr
.s_addr
& iface
->mask
.s_addr
;
142 iface
->bcast
.s_addr
= iface
->netaddr
.s_addr
| (~iface
->mask
.s_addr
);
146 return my_interfaces
;
150 escape_domain(ni_name name
)
158 for (p
= name
; *p
; p
++)
160 if ((*p
== '/') || (*p
== '\\')) extra
++;
163 newname
= malloc(strlen(name
) + extra
+ 1);
165 for (p
= name
; *p
; p
++)
167 if ((*p
== '/') || (*p
== '\\')) *s
++ = '\\';
177 finddomain(void *ni
, struct in_addr addr
, ni_name tag
)
187 status
= ni_root(ni
, &nid
);
188 if (status
!= NI_OK
) return NULL
;
190 status
= ni_lookup(ni
, &nid
, NAME_NAME
, NAME_MACHINES
, &idl
);
191 if (status
!= NI_OK
) return NULL
;
193 nid
.nii_object
= idl
.niil_val
[0];
194 ni_idlist_free(&idl
);
196 status
= ni_lookup(ni
, &nid
, NAME_IP_ADDRESS
, inet_ntoa(addr
), &idl
);
197 if (status
!= NI_OK
) return NULL
;
199 nid
.nii_object
= idl
.niil_val
[0];
200 ni_idlist_free(&idl
);
202 status
= ni_lookupprop(ni
, &nid
, NAME_SERVES
, &nl
);
203 if (status
!= NI_OK
) return NULL
;
205 for (i
= 0; i
< nl
.ninl_len
; i
++)
207 slash
= rindex(nl
.ninl_val
[i
], '/');
208 if (slash
== NULL
) continue;
210 if (ni_name_match(slash
+ 1, tag
))
213 domain
= escape_domain(nl
.ninl_val
[i
]);
214 ni_namelist_free(&nl
);
219 ni_namelist_free(&nl
);
225 sys_is_my_address(struct in_addr
*a
)
230 l
= sys_interfaces();
231 if (l
== NULL
) return 0;
233 for (i
= 0; i
< l
->count
; i
++)
235 if (a
->s_addr
== l
->interface
[i
].addr
.s_addr
) return 1;
241 ni_domainof(void *ni
, void *parent
)
243 struct sockaddr_in addr
;
247 interface_list_t
*ilist
;
250 status
= ni_addrtag(ni
, &addr
, &tag
);
251 if (status
!= NI_OK
) return ni_name_dup(NAME_UNKNOWN
);
253 dom
= finddomain(parent
, addr
.sin_addr
, tag
);
260 if (sys_is_my_address(&(addr
.sin_addr
)))
262 /* Try all my non-loopback interfaces */
263 ilist
= sys_interfaces();
264 if (ilist
== NULL
) return ni_name_dup(NAME_UNKNOWN
);
266 for (i
= 0; i
< ilist
->count
; i
++)
268 if (ilist
->interface
[i
].addr
.s_addr
== htonl(INADDR_LOOPBACK
)) continue;
270 addr
.sin_addr
.s_addr
= ilist
->interface
[i
].addr
.s_addr
;
271 dom
= finddomain(parent
, addr
.sin_addr
, tag
);
280 dom
= malloc(strlen(tag
) + 256);
281 sprintf(dom
, "%s@%s", tag
, inet_ntoa(addr
.sin_addr
.s_addr
));
287 _ni_pwdomain(void *ni
, ni_name
*buf
)
294 /* Open domain name */
295 nip
= ni_new(ni
, "..");
303 /* Get parent's name */
304 status
= _ni_pwdomain(nip
, buf
);
305 if (status
!= NI_OK
) return status
;
307 /* Get my name relative to my parent */
308 dom
= ni_domainof(ni
, nip
);
310 /* Append my relative name to my parent's name */
312 *buf
= realloc(*buf
, len
+ 1 + strlen(dom
) + 1);
314 strcpy(&(*buf
)[len
+ 1], dom
);
322 * Just call the recursive ni_pwdomain above, and then fix for case of root
326 ni_pwdomain(void *ni
, ni_name
*buf
)
331 status
= _ni_pwdomain(ni
, buf
);
334 if (*buf
!= NULL
) ni_name_free(buf
);