1/* 2 * Copyright (c) 2002, 2003, 2005, 2013, 2014 Apple 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 50static ssize_t 51readn(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 74static ssize_t 75writen(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__ 96int 97MOHInit(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__ 120int 121MOHDispose(int ref) 122{ 123 if (close(ref) == -1) { 124 return errno; 125 } 126 return 0; 127} 128 129 130__private_extern__ 131int 132MOHExec(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)) ? (uint32_t)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=%ld"), 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=%ld"), 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=%ld"), 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=%ld"), 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 208