]>
Commit | Line | Data |
---|---|---|
03fb6eb0 A |
1 | /* |
2 | * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
ad21edcc A |
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 | |
12 | * this file. | |
03fb6eb0 A |
13 | * |
14 | * The Original Code and all software distributed under the License are | |
ad21edcc | 15 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER |
03fb6eb0 A |
16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
ad21edcc A |
18 | * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the |
19 | * License for the specific language governing rights and limitations | |
20 | * under the License. | |
03fb6eb0 A |
21 | * |
22 | * @APPLE_LICENSE_HEADER_END@ | |
23 | */ | |
24 | /* | |
25 | * Copyright (C) 1990 by NeXT, Inc. All rights reserved. | |
26 | */ | |
27 | ||
28 | /* | |
29 | * ni_pwdomain function: present working domain for a netinfo handle | |
30 | * | |
31 | * usage: | |
32 | * ni_status ni_pwdomain(void *ni, ni_name *buf) | |
33 | * | |
34 | * pwd is returned in buf, which can be freed with ni_name_free | |
35 | */ | |
36 | #include <stdlib.h> | |
37 | #include <unistd.h> | |
38 | #include <sys/types.h> | |
39 | #include <sys/param.h> | |
40 | #include <stdio.h> | |
41 | #include <string.h> | |
42 | #include <netinfo/ni.h> | |
43 | #include <string.h> | |
44 | #include <sys/socket.h> | |
45 | #include <net/if.h> | |
46 | #include <sys/ioctl.h> | |
a0865d63 | 47 | #include "sys_interfaces.h" |
03fb6eb0 A |
48 | |
49 | extern char *inet_ntoa(); | |
50 | ||
51 | static const char NAME_NAME[] = "name"; | |
52 | static const char NAME_MACHINES[] = "machines"; | |
53 | static const char NAME_IP_ADDRESS[] = "ip_address"; | |
54 | static const char NAME_SERVES[] = "serves"; | |
55 | static const char NAME_UNKNOWN[] = "###UNKNOWN###"; | |
56 | ||
03fb6eb0 A |
57 | static ni_name |
58 | escape_domain(ni_name name) | |
59 | { | |
60 | int extra; | |
61 | char *p; | |
62 | char *s; | |
63 | ni_name newname; | |
64 | ||
65 | extra = 0; | |
66 | for (p = name; *p; p++) | |
67 | { | |
68 | if ((*p == '/') || (*p == '\\')) extra++; | |
69 | } | |
70 | ||
71 | newname = malloc(strlen(name) + extra + 1); | |
72 | s = newname; | |
73 | for (p = name; *p; p++) | |
74 | { | |
75 | if ((*p == '/') || (*p == '\\')) *s++ = '\\'; | |
76 | *s++ = *p; | |
77 | } | |
78 | ||
79 | *s = 0; | |
80 | return newname; | |
81 | ||
82 | } | |
83 | ||
84 | static char * | |
85 | finddomain(void *ni, struct in_addr addr, ni_name tag) | |
86 | { | |
87 | ni_id nid; | |
88 | ni_idlist idl; | |
89 | ni_namelist nl; | |
90 | ni_index i; | |
91 | ni_name slash; | |
92 | ni_name domain; | |
93 | ni_status status; | |
94 | ||
95 | status = ni_root(ni, &nid); | |
96 | if (status != NI_OK) return NULL; | |
97 | ||
98 | status = ni_lookup(ni, &nid, NAME_NAME, NAME_MACHINES, &idl); | |
99 | if (status != NI_OK) return NULL; | |
100 | ||
101 | nid.nii_object = idl.niil_val[0]; | |
102 | ni_idlist_free(&idl); | |
103 | ||
104 | status = ni_lookup(ni, &nid, NAME_IP_ADDRESS, inet_ntoa(addr), &idl); | |
105 | if (status != NI_OK) return NULL; | |
106 | ||
107 | nid.nii_object = idl.niil_val[0]; | |
108 | ni_idlist_free(&idl); | |
109 | ||
110 | status = ni_lookupprop(ni, &nid, NAME_SERVES, &nl); | |
111 | if (status != NI_OK) return NULL; | |
112 | ||
113 | for (i = 0; i < nl.ninl_len; i++) | |
114 | { | |
115 | slash = rindex(nl.ninl_val[i], '/'); | |
116 | if (slash == NULL) continue; | |
117 | ||
118 | if (ni_name_match(slash + 1, tag)) | |
119 | { | |
120 | *slash = 0; | |
121 | domain = escape_domain(nl.ninl_val[i]); | |
122 | ni_namelist_free(&nl); | |
123 | return domain; | |
124 | } | |
125 | } | |
126 | ||
127 | ni_namelist_free(&nl); | |
128 | ||
129 | return NULL; | |
130 | } | |
131 | ||
03fb6eb0 A |
132 | static char * |
133 | ni_domainof(void *ni, void *parent) | |
134 | { | |
135 | struct sockaddr_in addr; | |
136 | ni_name tag; | |
137 | ni_name dom; | |
138 | ni_status status; | |
139 | interface_list_t *ilist; | |
140 | int i; | |
141 | ||
142 | status = ni_addrtag(ni, &addr, &tag); | |
143 | if (status != NI_OK) return ni_name_dup(NAME_UNKNOWN); | |
144 | ||
145 | dom = finddomain(parent, addr.sin_addr, tag); | |
146 | if (dom != NULL) | |
147 | { | |
148 | ni_name_free(&tag); | |
149 | return dom; | |
150 | } | |
151 | ||
c29f2fcc | 152 | ilist = _libinfo_ni_sys_interfaces(); |
a0865d63 | 153 | if (ilist == NULL) return ni_name_dup(NAME_UNKNOWN); |
c29f2fcc | 154 | if (_libinfo_ni_sys_is_my_address(ilist, &(addr.sin_addr))) |
03fb6eb0 A |
155 | { |
156 | /* Try all my non-loopback interfaces */ | |
03fb6eb0 A |
157 | for (i = 0; i < ilist->count; i++) |
158 | { | |
159 | if (ilist->interface[i].addr.s_addr == htonl(INADDR_LOOPBACK)) continue; | |
160 | ||
161 | addr.sin_addr.s_addr = ilist->interface[i].addr.s_addr; | |
162 | dom = finddomain(parent, addr.sin_addr, tag); | |
163 | if (dom != NULL) | |
164 | { | |
165 | ni_name_free(&tag); | |
c29f2fcc | 166 | _libinfo_ni_sys_interfaces_release(ilist); |
03fb6eb0 A |
167 | return dom; |
168 | } | |
169 | } | |
170 | } | |
c29f2fcc | 171 | _libinfo_ni_sys_interfaces_release(ilist); |
03fb6eb0 A |
172 | |
173 | dom = malloc(strlen(tag) + 256); | |
174 | sprintf(dom, "%s@%s", tag, inet_ntoa(addr.sin_addr.s_addr)); | |
175 | ni_name_free(&tag); | |
176 | return dom; | |
177 | } | |
178 | ||
179 | static ni_status | |
180 | _ni_pwdomain(void *ni, ni_name *buf) | |
181 | { | |
182 | void *nip; | |
183 | ni_status status; | |
184 | int len; | |
185 | char *dom; | |
186 | ||
187 | /* Open domain name */ | |
188 | nip = ni_new(ni, ".."); | |
189 | if (nip == NULL) | |
190 | { | |
191 | (*buf) = malloc(2); | |
192 | (*buf)[0] = 0; | |
193 | return NI_OK; | |
194 | } | |
195 | ||
196 | /* Get parent's name */ | |
197 | status = _ni_pwdomain(nip, buf); | |
198 | if (status != NI_OK) return status; | |
199 | ||
200 | /* Get my name relative to my parent */ | |
201 | dom = ni_domainof(ni, nip); | |
202 | ||
203 | /* Append my relative name to my parent's name */ | |
204 | len = strlen(*buf); | |
205 | *buf = realloc(*buf, len + 1 + strlen(dom) + 1); | |
206 | (*buf)[len] = '/'; | |
207 | strcpy(&(*buf)[len + 1], dom); | |
208 | ni_name_free(&dom); | |
209 | ni_free(nip); | |
210 | ||
211 | return NI_OK; | |
212 | } | |
213 | ||
214 | /* | |
215 | * Just call the recursive ni_pwdomain above, and then fix for case of root | |
216 | * domain or error | |
217 | */ | |
218 | ni_status | |
219 | ni_pwdomain(void *ni, ni_name *buf) | |
220 | { | |
221 | ni_status status; | |
222 | ||
223 | *buf = NULL; | |
224 | status = _ni_pwdomain(ni, buf); | |
225 | if (status != NI_OK) | |
226 | { | |
227 | if (*buf != NULL) ni_name_free(buf); | |
228 | return status; | |
229 | } | |
230 | ||
231 | if ((*buf)[0] == 0) | |
232 | { | |
233 | (*buf)[0] = '/'; | |
234 | (*buf)[1] = 0; | |
235 | } | |
236 | ||
237 | return NI_OK; | |
238 | } |