]> git.saurik.com Git - apple/syslog.git/blob - syslogd.tproj/udp_in.c
3f6affd3461e6ad5ed9a5a588ba0e5ad999bcbe9
[apple/syslog.git] / syslogd.tproj / udp_in.c
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
27 struct _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
53 static int nsock = 0;
54 static int ufd[MAXSOCK];
55 static dispatch_source_t ufd_src[MAXSOCK];
56
57 static char uline[MAXLINE + 1];
58
59 static dispatch_source_t in_src[MAXSOCK];
60 static dispatch_queue_t in_queue;
61
62 #define FMT_LEGACY 0
63 #define FMT_ASL 1
64
65 void
66 udp_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
109 int
110 udp_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. */
188 int
189 udp_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
215 int
216 udp_in_reset(void)
217 {
218 if (udp_in_close() != 0) return -1;
219 return udp_in_init();
220 }
221
222 #endif /* TARGET_IPHONE_SIMULATOR */