1/* 2 * Copyright (c) 2004-2011 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#include <TargetConditionals.h> 25 26#if TARGET_IPHONE_SIMULATOR 27struct _not_empty; 28#else 29 30#include <sys/types.h> 31#include <sys/stat.h> 32#include <sys/socket.h> 33#include <netinet/in.h> 34#include <arpa/inet.h> 35#include <sys/un.h> 36#include <sys/uio.h> 37#include <stdio.h> 38#include <stdlib.h> 39#include <string.h> 40#include <fcntl.h> 41#include <errno.h> 42#include <unistd.h> 43#include <netdb.h> 44#include "daemon.h" 45 46#define forever for(;;) 47 48#define UDP_SOCKET_NAME "NetworkListener" 49#define MY_ID "udp_in" 50#define MAXLINE 4096 51 52#define MAXSOCK 16 53static int nsock = 0; 54static int ufd[MAXSOCK]; 55static dispatch_source_t ufd_src[MAXSOCK]; 56 57static char uline[MAXLINE + 1]; 58 59static dispatch_source_t in_src[MAXSOCK]; 60static dispatch_queue_t in_queue; 61 62#define FMT_LEGACY 0 63#define FMT_ASL 1 64 65void 66udp_in_acceptmsg(int fd) 67{ 68 socklen_t fromlen; 69 ssize_t len; 70 struct sockaddr_storage from; 71 char fromstr[64], *r, *p; 72 struct sockaddr_in *s4; 73 struct sockaddr_in6 *s6; 74 asl_msg_t *m; 75 76 fromlen = sizeof(struct sockaddr_storage); 77 memset(&from, 0, fromlen); 78 79 len = recvfrom(fd, uline, MAXLINE, 0, (struct sockaddr *)&from, &fromlen); 80 if (len <= 0) return; 81 82 fromstr[0] = '\0'; 83 r = NULL; 84 85 if (from.ss_family == AF_INET) 86 { 87 s4 = (struct sockaddr_in *)&from; 88 inet_ntop(from.ss_family, &(s4->sin_addr), fromstr, 64); 89 r = fromstr; 90 asldebug("%s: fd %d recvfrom %s len %d\n", MY_ID, fd, fromstr, len); 91 } 92 else if (from.ss_family == AF_INET6) 93 { 94 s6 = (struct sockaddr_in6 *)&from; 95 inet_ntop(from.ss_family, &(s6->sin6_addr), fromstr, 64); 96 r = fromstr; 97 asldebug("%s: fd %d recvfrom %s len %d\n", MY_ID, fd, fromstr, len); 98 } 99 100 uline[len] = '\0'; 101 102 p = strrchr(uline, '\n'); 103 if (p != NULL) *p = '\0'; 104 105 m = asl_input_parse(uline, len, r, SOURCE_UDP_SOCKET); 106 process_message(m, SOURCE_UDP_SOCKET); 107} 108 109int 110udp_in_init() 111{ 112 int i, rbufsize, len, fd; 113 launch_data_t sockets_dict, fd_array, fd_dict; 114 static dispatch_once_t once; 115 116 dispatch_once(&once, ^{ 117 in_queue = dispatch_queue_create(MY_ID, NULL); 118 }); 119 120 asldebug("%s: init\n", MY_ID); 121 if (nsock > 0) return 0; 122 123 if (global.launch_dict == NULL) 124 { 125 asldebug("%s: launchd dict is NULL\n", MY_ID); 126 return -1; 127 } 128 129 sockets_dict = launch_data_dict_lookup(global.launch_dict, LAUNCH_JOBKEY_SOCKETS); 130 if (sockets_dict == NULL) 131 { 132 asldebug("%s: launchd lookup of LAUNCH_JOBKEY_SOCKETS failed\n", MY_ID); 133 return -1; 134 } 135 136 fd_array = launch_data_dict_lookup(sockets_dict, UDP_SOCKET_NAME); 137 if (fd_array == NULL) 138 { 139 asldebug("%s: launchd lookup of UDP_SOCKET_NAME failed\n", MY_ID); 140 return -1; 141 } 142 143 nsock = launch_data_array_get_count(fd_array); 144 if (nsock <= 0) 145 { 146 asldebug("%s: launchd fd array is empty\n", MY_ID); 147 return -1; 148 } 149 150 for (i = 0; i < nsock; i++) 151 { 152 ufd[i] = -1; 153 154 fd_dict = launch_data_array_get_index(fd_array, i); 155 if (fd_dict == NULL) 156 { 157 asldebug("%s: launchd file discriptor array element 0 is NULL\n", MY_ID); 158 return -1; 159 } 160 161 fd = launch_data_get_fd(fd_dict); 162 163 rbufsize = 128 * 1024; 164 len = sizeof(rbufsize); 165 166 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rbufsize, len) < 0) 167 { 168 asldebug("%s: couldn't set receive buffer size for file descriptor %d: %s\n", MY_ID, fd, strerror(errno)); 169 } 170 171 if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) 172 { 173 asldebug("%s: couldn't set O_NONBLOCK for file descriptor %d: %s\n", MY_ID, fd, strerror(errno)); 174 } 175 176 ufd[i] = fd; 177 178 in_src[i] = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, (uintptr_t)fd, 0, in_queue); 179 dispatch_source_set_event_handler(in_src[i], ^{ udp_in_acceptmsg(fd); }); 180 181 dispatch_resume(in_src[i]); 182 } 183 184 return 0; 185} 186 187/* N.B. Does NOT close fds. They "belong" to launchd. */ 188int 189udp_in_close(void) 190{ 191 int i; 192 193 if (nsock == 0) return -1; 194 195 for (i = 0; i < nsock; i++) 196 { 197 if (ufd_src[i] != NULL) 198 { 199 dispatch_source_cancel(in_src[i]); 200 dispatch_release(in_src[i]); 201 in_src[i] = NULL; 202 } 203 204 if (ufd[i] != -1) 205 { 206 ufd[i] = -1; 207 } 208 } 209 210 nsock = 0; 211 212 return 0; 213} 214 215int 216udp_in_reset(void) 217{ 218 if (udp_in_close() != 0) return -1; 219 return udp_in_init(); 220} 221 222#endif /* TARGET_IPHONE_SIMULATOR */ 223