1/* 2 * Copyright (c) 2000 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/* ----------------------------------------------------------------------------- 26includes 27----------------------------------------------------------------------------- */ 28 29#include <stdio.h> 30#include <stdlib.h> 31#include <string.h> 32#include <unistd.h> 33#include <sys/queue.h> 34#import <CoreFoundation/CFSocket.h> 35#include <mach/mach.h> 36#include <mach/mach_error.h> 37#include <CoreFoundation/CFMachPort.h> 38#include <CoreFoundation/CFBundle.h> 39 40#include "ppp_msg.h" 41#include "ppp_client.h" 42#include "ppp_utils.h" 43#include "ppp_mach_server.h" 44#include "ppp_socket_server.h" 45 46/* ----------------------------------------------------------------------------- 47definitions 48----------------------------------------------------------------------------- */ 49 50int ppp_clientgone(void *client); 51 52TAILQ_HEAD(, client) client_head; 53 54 55/* ----------------------------------------------------------------------------- 56----------------------------------------------------------------------------- */ 57u_long client_init_all () 58{ 59 60 TAILQ_INIT(&client_head); 61 return 0; 62} 63 64/* ----------------------------------------------------------------------------- 65----------------------------------------------------------------------------- */ 66struct client *client_new_socket (CFSocketRef ref, int priviledged, uid_t uid, gid_t gid) 67{ 68 struct client *client; 69 70 client = malloc(sizeof(struct client)); 71 if (!client) 72 return 0; // very bad... 73 74 bzero(client, sizeof(struct client)); 75 76 CFRetain(ref); 77 client->socketRef = ref; 78 if (priviledged) 79 client->flags |= CLIENT_FLAG_PRIVILEDGED; 80 client->uid = uid; 81 client->gid = gid; 82 client->flags |= CLIENT_FLAG_IS_SOCKET; 83 TAILQ_INIT(&client->opts_head); 84 85 TAILQ_INSERT_TAIL(&client_head, client, next); 86 87 return client; 88} 89 90/* ----------------------------------------------------------------------------- 91----------------------------------------------------------------------------- */ 92struct client *client_new_mach (CFMachPortRef port, CFRunLoopSourceRef rls, CFStringRef serviceID, uid_t uid, gid_t gid, mach_port_t bootstrap, mach_port_t notify_port) 93{ 94 struct client *client; 95 96 client = malloc(sizeof(struct client)); 97 if (!client) 98 return 0; // very bad... 99 100 bzero(client, sizeof(struct client)); 101 102 CFRetain(port); 103 CFRetain(rls); 104 CFRetain(serviceID); 105 client->sessionPortRef = port; 106 client->sessionRls = rls; 107 client->serviceID = serviceID; 108 client->uid = uid; 109 client->gid = gid; 110 client->bootstrap_port = bootstrap; 111 client->notify_port = notify_port; 112 client->flags &= ~CLIENT_FLAG_IS_SOCKET; 113 TAILQ_INIT(&client->opts_head); 114 115 TAILQ_INSERT_TAIL(&client_head, client, next); 116 117 return client; 118} 119 120/* ----------------------------------------------------------------------------- 121----------------------------------------------------------------------------- */ 122void client_dispose (struct client *client) 123{ 124 struct client_opts *opts; 125 126 TAILQ_REMOVE(&client_head, client, next); 127 128 ppp_clientgone(client); 129 130 while (opts = TAILQ_FIRST(&(client->opts_head))) { 131 132 TAILQ_REMOVE(&(client->opts_head), opts, next); 133 CFRelease(opts->serviceid); 134 free(opts); 135 } 136 137 client->notify_link = 0; 138 if (client->notify_serviceid) { 139 free(client->notify_serviceid); 140 client->notify_serviceid = 0; 141 } 142 143 if (client->msg) { 144 my_Deallocate(client->msg, client->msgtotallen + 1); 145 client->msg = 0; 146 } 147 client->msglen = 0; 148 client->msgtotallen = 0; 149 150 if (client->bootstrap_port != MACH_PORT_NULL) { 151 mach_port_deallocate(mach_task_self(), client->bootstrap_port); 152 client->bootstrap_port = MACH_PORT_NULL; 153 } 154 155 if (client->notify_port != MACH_PORT_NULL) { 156 mach_port_deallocate(mach_task_self(), client->notify_port); 157 client->notify_port = MACH_PORT_NULL; 158 } 159 160 if (client->socketRef) { 161 CFSocketInvalidate(client->socketRef); 162 my_CFRelease(client->socketRef); 163 } 164 165 if (client->sessionPortRef) { 166 CFMachPortInvalidate(client->sessionPortRef); 167 my_CFRelease(client->sessionPortRef); 168 } 169 170 if (client->sessionRls) { 171 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), client->sessionRls, kCFRunLoopDefaultMode); 172 my_CFRelease(client->sessionRls); 173 } 174 175 my_CFRelease(client->serviceID); 176 free(client); 177} 178 179/* ----------------------------------------------------------------------------- 180----------------------------------------------------------------------------- */ 181CFMutableDictionaryRef client_newoptset (struct client *client, CFStringRef serviceid) 182{ 183 struct client_opts *opts; 184 185 opts = malloc(sizeof(struct client_opts)); 186 if (!opts) 187 return 0; // very bad... 188 189 bzero(opts, sizeof(struct client_opts)); 190 191 opts->opts = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 192 if (opts->opts == 0) { 193 free(opts); 194 return 0; // very bad... 195 } 196 197 opts->serviceid = serviceid; 198 CFRetain(opts->serviceid); 199 TAILQ_INSERT_TAIL(&(client->opts_head), opts, next); 200 201 return opts->opts; 202} 203 204/* ----------------------------------------------------------------------------- 205----------------------------------------------------------------------------- */ 206CFMutableDictionaryRef client_findoptset (struct client *client, CFStringRef serviceid) 207{ 208 struct client_opts *opts; 209 210 TAILQ_FOREACH(opts, &(client->opts_head), next) 211 if (CFStringCompare(opts->serviceid, serviceid, 0) == kCFCompareEqualTo) 212 return opts->opts; 213 214 return 0; 215} 216 217/* ----------------------------------------------------------------------------- 218----------------------------------------------------------------------------- */ 219u_long client_notify (CFStringRef serviceID, u_char* sid, u_int32_t link, u_long event, u_long error, int notification) 220{ 221 struct client *client; 222 int doit; 223 224 TAILQ_FOREACH(client, &client_head, next) { 225 doit = 0; 226 227 if (client->flags & notification) { 228 229 if (client->flags & CLIENT_FLAG_IS_SOCKET) { 230 if (client->notify_serviceid) { 231 doit = ((client->notify_serviceid[0] == 0) // any service 232 || !strcmp(client->notify_serviceid, sid)); 233 } 234 else { 235 doit = ((client->notify_link == link) // exact same link 236 || ((client->notify_link >> 16) == 0xFFFF) // all kind of links 237 || (((client->notify_link >> 16) == (link >> 16))// all links of that kind 238 && ((client->notify_link >> 16) == 0xFFFF))); 239 } 240 } 241 else { 242 doit = CFStringCompare(client->serviceID, serviceID, 0) == kCFCompareEqualTo; 243 } 244 } 245 246 if (doit) { 247 if (client->flags & CLIENT_FLAG_IS_SOCKET) 248 socket_client_notify (client->socketRef, client->notify_serviceid ? sid : 0, link, event, error, client->flags); 249 else 250 mach_client_notify (client->notify_port, client->serviceID, event, error); 251 } 252 } 253 return 0; 254} 255 256/* ----------------------------------------------------------------------------- 257----------------------------------------------------------------------------- */ 258struct client *client_findbysocketref(CFSocketRef ref) 259{ 260 struct client *client; 261 262 TAILQ_FOREACH(client, &client_head, next) 263 if (client->socketRef == ref) 264 return client; 265 266 return 0; 267} 268 269/* ----------------------------------------------------------------------------- 270----------------------------------------------------------------------------- */ 271struct client *client_findbymachport(mach_port_t port) 272{ 273 struct client *client; 274 275 TAILQ_FOREACH(client, &client_head, next) 276 if (client->sessionPortRef 277 && port == CFMachPortGetPort(client->sessionPortRef)) 278 return client; 279 280 return 0; 281} 282