]> git.saurik.com Git - apple/configd.git/blob - SystemConfiguration.fproj/moh.c
configd-395.10.tar.gz
[apple/configd.git] / SystemConfiguration.fproj / moh.c
1 /*
2 * Copyright (c) 2002, 2003, 2005 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 /*
25 * Modification History
26 *
27 * May 29, 2002 Roger Smith <rsmith@apple.com>
28 * - initial revision
29 */
30
31 #include <stdio.h>
32 #include <unistd.h>
33 #include <sys/types.h>
34 #include <sys/errno.h>
35 #include <sys/socket.h>
36 #include <sys/un.h>
37
38 #include <SystemConfiguration/SystemConfiguration.h>
39 #include <SystemConfiguration/SCPrivate.h>
40
41 #include "moh.h"
42 #include "moh_msg.h"
43
44 // Note: right now we are not currently using the deviceName. This could be the raw
45 // tty name such as "modem" since this is guaranteed to be unique in the /dev.
46 // We would use this deviceName to differientate between multiple MOH devices
47 // present in the system when we create the socket.
48
49
50 static ssize_t
51 readn(int ref, void *data, size_t len)
52 {
53 size_t left = len;
54 ssize_t n;
55 void *p = data;
56
57 while (left > 0) {
58 if ((n = read(ref, p, left)) == -1) {
59 if (errno != EINTR) {
60 return -1;
61 }
62 n = 0;
63 } else if (n == 0) {
64 break; /* EOF */
65 }
66
67 left -= n;
68 p += n;
69 }
70 return (len - left);
71 }
72
73
74 static ssize_t
75 writen(int ref, const void *data, size_t len)
76 {
77 size_t left = len;
78 ssize_t n;
79 const void *p = data;
80
81 while (left > 0) {
82 if ((n = write(ref, p, left)) == -1) {
83 if (errno != EINTR) {
84 return -1;
85 }
86 n = 0;
87 }
88 left -= n;
89 p += n;
90 }
91 return len;
92 }
93
94
95 __private_extern__
96 int
97 MOHInit(int *ref, CFStringRef deviceName)
98 {
99 int sock;
100 int status;
101 struct sockaddr_un sun;
102
103 sock = socket(AF_LOCAL, SOCK_STREAM, 0);
104
105 bzero(&sun, sizeof(sun));
106 sun.sun_family = AF_LOCAL;
107 strncpy(sun.sun_path, MOH_PATH, sizeof(sun.sun_path));
108
109 status = connect(sock, (struct sockaddr *)&sun, sizeof(sun));
110 if (status == -1) {
111 return errno;
112 }
113
114 *ref = sock;
115 return 0;
116 }
117
118
119 __private_extern__
120 int
121 MOHDispose(int ref)
122 {
123 if (close(ref) == -1) {
124 return errno;
125 }
126 return 0;
127 }
128
129
130 __private_extern__
131 int
132 MOHExec(int ref,
133 uint32_t link,
134 uint32_t cmd,
135 void *request,
136 size_t requestLen,
137 void **reply,
138 size_t *replyLen)
139 {
140 struct moh_msg_hdr msg;
141 char *buf = NULL;
142 ssize_t n;
143
144 bzero(&msg, sizeof(msg));
145 msg.m_type = cmd;
146 msg.m_link = link;
147 msg.m_len = ((request != NULL) && (requestLen > 0)) ? requestLen : 0;
148
149 // send the command
150 n = writen(ref, &msg, sizeof(msg));
151 if (n == -1) {
152 SCLog(_sc_verbose, LOG_ERR, CFSTR("MOHExec writen() failed: %s"), strerror(errno));
153 return errno;
154 } else if (n != sizeof(msg)) {
155 SCLog(_sc_verbose, LOG_ERR, CFSTR("MOHExec writen() failed: wrote=%d"), n);
156 return -1;
157 }
158
159 if ((request != NULL) && (requestLen > 0)) {
160 n = writen(ref, request, requestLen);
161 if (n == -1) {
162 SCLog(_sc_verbose, LOG_ERR, CFSTR("MOHExec writen() failed: %s"), strerror(errno));
163 return errno;
164 } else if (n != (ssize_t)requestLen) {
165 SCLog(_sc_verbose, LOG_ERR, CFSTR("MOHExec writen() failed: wrote=%d"), n);
166 return -1;
167 }
168 }
169
170 // always expect a reply
171 n = readn(ref, &msg, sizeof(msg));
172 if (n == -1) {
173 SCLog(_sc_verbose, LOG_ERR, CFSTR("MOHExec readn() failed: error=%s"), strerror(errno));
174 return errno;
175 } else if (n != sizeof(msg)) {
176 SCLog(_sc_verbose, LOG_ERR, CFSTR("MOHExec readn() failed: insufficent data, read=%d"), n);
177 return -1;
178 }
179
180 if (msg.m_len) {
181 buf = CFAllocatorAllocate(NULL, msg.m_len, 0);
182 if (buf) {
183 // read reply
184 n = readn(ref, buf, msg.m_len);
185 if (n == -1) {
186 SCLog(_sc_verbose, LOG_ERR, CFSTR("MOHExec readn() failed: error=%s"), strerror(errno));
187 CFAllocatorDeallocate(NULL, buf);
188 return errno;
189 } else if (n != (ssize_t)msg.m_len) {
190 SCLog(_sc_verbose, LOG_ERR, CFSTR("MOHExec readn() failed: insufficent data, read=%d"), n);
191 CFAllocatorDeallocate(NULL, buf);
192 return -1;
193 }
194 }
195 }
196
197 if (reply && replyLen) {
198 *reply = buf;
199 *replyLen = msg.m_len;
200 } else if (buf) {
201 // if additional returned data is unwanted
202 CFAllocatorDeallocate(NULL, buf);
203 }
204
205 return msg.m_result;
206 }
207