]> git.saurik.com Git - apple/syslog.git/blame_incremental - syslogd.tproj/udp_in.c
syslog-14.2.tar.gz
[apple/syslog.git] / syslogd.tproj / udp_in.c
... / ...
CommitLineData
1/*
2 * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * "Portions Copyright (c) 2004 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License."
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25#include <sys/types.h>
26#include <sys/stat.h>
27#include <sys/socket.h>
28#include <netinet/in.h>
29#include <arpa/inet.h>
30#include <sys/un.h>
31#include <sys/uio.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include <string.h>
35#include <fcntl.h>
36#include <errno.h>
37#include <unistd.h>
38#include <netdb.h>
39#include "daemon.h"
40
41#define forever for(;;)
42
43#define MY_ID "udp_in"
44#define MAXLINE 4096
45
46#define MAXSOCK 16
47static int nsock = 0;
48static int ufd[MAXSOCK];
49
50static char uline[MAXLINE + 1];
51
52#define FMT_LEGACY 0
53#define FMT_ASL 1
54
55asl_msg_t *
56udp_convert(int fmt, char *s, int len, char *from)
57{
58 char *out;
59 asl_msg_t *m;
60
61 out = NULL;
62 m = NULL;
63
64 if (fmt == FMT_ASL)
65 {
66 m = asl_msg_from_string(s);
67 if (from != NULL) asl_set(m, ASL_KEY_HOST, from);
68 return m;
69 }
70
71 return asl_syslog_input_convert(uline, len, from, 0);
72}
73
74asl_msg_t *
75udp_in_acceptmsg(int fd)
76{
77 int format, status, x, fromlen;
78 size_t off;
79 ssize_t len;
80 struct sockaddr_storage from;
81 char fromstr[64], *r, *p;
82 struct sockaddr_in *s4;
83 struct sockaddr_in6 *s6;
84
85 fromlen = sizeof(struct sockaddr_storage);
86 memset(&from, 0, fromlen);
87
88 len = recvfrom(fd, uline, MAXLINE, 0, (struct sockaddr *)&from, &fromlen);
89 if (len <= 0) return NULL;
90
91 fromstr[0] = '\0';
92 r = NULL;
93
94 if (from.ss_family == AF_INET)
95 {
96 s4 = (struct sockaddr_in *)&from;
97 inet_ntop(from.ss_family, &(s4->sin_addr), fromstr, 64);
98 r = fromstr;
99 asldebug("%s: recvfrom %s len %d\n", MY_ID, fromstr, len);
100 }
101 else if (from.ss_family == AF_INET6)
102 {
103 s6 = (struct sockaddr_in6 *)&from;
104 inet_ntop(from.ss_family, &(s6->sin6_addr), fromstr, 64);
105 r = fromstr;
106 asldebug("%s: recvfrom %s len %d\n", MY_ID, fromstr, len);
107 }
108
109 uline[len] = '\0';
110
111 p = strrchr(uline, '\n');
112 if (p != NULL) *p = '\0';
113
114
115 /*
116 * Determine if the input is "old" syslog format or new ASL format.
117 * Old format lines should start with "<", but they can just be
118 * straight text. ASL input starts with a length (10 bytes)
119 * followed by a space and a '['.
120 */
121 format = FMT_LEGACY;
122 off = 0;
123
124 if ((uline[0] != '<') && (len > 11))
125 {
126 status = sscanf(uline, "%d ", &x);
127 if (status == 1)
128 {
129 if ((uline[10] == ' ') && (uline[11] == '['))
130 {
131 format = FMT_ASL;
132 off = 11;
133 }
134 }
135 }
136
137 return udp_convert(format, uline+off, len-off, r);
138}
139
140int
141udp_in_init(void)
142{
143 struct addrinfo hints, *gai, *ai;
144 int status, i;
145
146 asldebug("%s: init\n", MY_ID);
147 if (nsock > 0) return 0;
148
149 memset(&hints, 0, sizeof(hints));
150 hints.ai_flags = AI_PASSIVE;
151 hints.ai_family = PF_UNSPEC;
152 hints.ai_socktype = SOCK_DGRAM;
153
154 status = getaddrinfo(NULL, "syslog", &hints, &gai);
155 if (status != 0) return -1;
156
157 for (ai = gai; (ai != NULL) && (nsock < MAXSOCK); ai = ai->ai_next)
158 {
159 ufd[nsock] = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
160 if (ufd[nsock] < 0)
161 {
162 asldebug("%s: socket: %s\n", MY_ID, strerror(errno));
163 continue;
164 }
165
166 if (bind(ufd[nsock], ai->ai_addr, ai->ai_addrlen) < 0)
167 {
168 asldebug("%s: bind: %s\n", MY_ID, strerror(errno));
169 close(ufd[nsock]);
170 continue;
171 }
172
173 nsock++;
174 }
175
176 freeaddrinfo(gai);
177
178 if (nsock == 0)
179 {
180 asldebug("%s: no input sockets\n", MY_ID);
181 return -1;
182 }
183
184 for (i = 0; i < nsock; i++) aslevent_addfd(ufd[i], udp_in_acceptmsg, NULL, NULL);
185 return 0;
186}
187
188int
189udp_in_reset(void)
190{
191 return 0;
192}
193
194int
195udp_in_close(void)
196{
197 int i;
198
199 if (nsock == 0) return 1;
200
201 for (i = 0; i < nsock; i++)
202 {
203 close(ufd[i]);
204 ufd[i] = -1;
205 }
206
207 nsock = 0;
208
209 return 0;
210}