]> git.saurik.com Git - apple/syslog.git/blob - syslogd.tproj/udp_in.c
syslog-13.1.tar.gz
[apple/syslog.git] / syslogd.tproj / udp_in.c
1 /*
2 * Copyright (c) 2004 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 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <sys/socket.h>
27 #include <netinet/in.h>
28 #include <arpa/inet.h>
29 #include <sys/un.h>
30 #include <sys/uio.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <fcntl.h>
35 #include <errno.h>
36 #include <unistd.h>
37 #include <netdb.h>
38 #include "daemon.h"
39
40 #define forever for(;;)
41
42 #define MY_ID "udp_in"
43 #define MAXLINE 4096
44
45 #define MAXSOCK 16
46 static int nsock = 0;
47 static int ufd[MAXSOCK];
48
49 static char uline[MAXLINE + 1];
50
51 #define FMT_LEGACY 0
52 #define FMT_ASL 1
53
54 asl_msg_t *
55 udp_convert(int fmt, char *s, int len, char *from)
56 {
57 char *out;
58 asl_msg_t *m;
59
60 out = NULL;
61 m = NULL;
62
63 if (fmt == FMT_ASL)
64 {
65 m = asl_msg_from_string(s);
66 if (from != NULL) asl_set(m, ASL_KEY_HOST, from);
67 return m;
68 }
69
70 return asl_syslog_input_convert(uline, len, from, 0);
71 }
72
73 asl_msg_t *
74 udp_in_acceptmsg(int fd)
75 {
76 int format, status, x, fromlen;
77 size_t off;
78 ssize_t len;
79 struct sockaddr_storage from;
80 char fromstr[64], *r, *p;
81 struct sockaddr_in *s4;
82 struct sockaddr_in6 *s6;
83
84 fromlen = sizeof(struct sockaddr_storage);
85 memset(&from, 0, fromlen);
86
87 len = recvfrom(fd, uline, MAXLINE, 0, (struct sockaddr *)&from, &fromlen);
88 if (len <= 0) return NULL;
89
90 fromstr[0] = '\0';
91 r = NULL;
92
93 if (from.ss_family == AF_INET)
94 {
95 s4 = (struct sockaddr_in *)&from;
96 inet_ntop(from.ss_family, &(s4->sin_addr), fromstr, 64);
97 r = fromstr;
98 asldebug("%s: recvfrom %s len %d\n", MY_ID, fromstr, len);
99 }
100 else if (from.ss_family == AF_INET6)
101 {
102 s6 = (struct sockaddr_in6 *)&from;
103 inet_ntop(from.ss_family, &(s6->sin6_addr), fromstr, 64);
104 r = fromstr;
105 asldebug("%s: recvfrom %s len %d\n", MY_ID, fromstr, len);
106 }
107
108 uline[len] = '\0';
109
110 p = strrchr(uline, '\n');
111 if (p != NULL) *p = '\0';
112
113
114 /*
115 * Determine if the input is "old" syslog format or new ASL format.
116 * Old format lines should start with "<", but they can just be
117 * straight text. ASL input starts with a length (10 bytes)
118 * followed by a space and a '['.
119 */
120 format = FMT_LEGACY;
121 off = 0;
122
123 if ((uline[0] != '<') && (len > 11))
124 {
125 status = sscanf(uline, "%d ", &x);
126 if (status == 1)
127 {
128 if ((uline[10] == ' ') && (uline[11] == '['))
129 {
130 format = FMT_ASL;
131 off = 11;
132 }
133 }
134 }
135
136 return udp_convert(format, uline+off, len-off, r);
137 }
138
139 int
140 udp_in_init(void)
141 {
142 struct addrinfo hints, *gai, *ai;
143 int status, i;
144
145 asldebug("%s: init\n", MY_ID);
146 if (nsock > 0) return 0;
147
148 memset(&hints, 0, sizeof(hints));
149 hints.ai_flags = AI_PASSIVE;
150 hints.ai_family = PF_UNSPEC;
151 hints.ai_socktype = SOCK_DGRAM;
152
153 status = getaddrinfo(NULL, "syslog", &hints, &gai);
154 if (status != 0) return -1;
155
156 for (ai = gai; (ai != NULL) && (nsock < MAXSOCK); ai = ai->ai_next)
157 {
158 ufd[nsock] = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
159 if (ufd[nsock] < 0)
160 {
161 asldebug("%s: socket: %s\n", MY_ID, strerror(errno));
162 continue;
163 }
164
165 if (bind(ufd[nsock], ai->ai_addr, ai->ai_addrlen) < 0)
166 {
167 asldebug("%s: bind: %s\n", MY_ID, strerror(errno));
168 close(ufd[nsock]);
169 continue;
170 }
171
172 nsock++;
173 }
174
175 freeaddrinfo(gai);
176
177 if (nsock == 0)
178 {
179 asldebug("%s: no input sockets\n", MY_ID);
180 return -1;
181 }
182
183 for (i = 0; i < nsock; i++) aslevent_addfd(ufd[i], udp_in_acceptmsg, NULL, NULL);
184 return 0;
185 }
186
187 int
188 udp_in_reset(void)
189 {
190 return 0;
191 }
192
193 int
194 udp_in_close(void)
195 {
196 int i;
197
198 if (nsock == 0) return 1;
199
200 for (i = 0; i < nsock; i++)
201 {
202 close(ufd[i]);
203 ufd[i] = -1;
204 }
205
206 nsock = 0;
207
208 return 0;
209 }