Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 214 lines (179 sloc) 5.312 kb
d972029 @msantos The actual source code ... of a sort
authored
1 /*
2 * Socket over DNS server.
3 *
8331a2d @msantos Update copyright date
authored
4 * Copyright (c) 2009-2011 Michael Santos <michael.santos@gmail.com>
a0e301b @msantos spurious trailing whitespace blitz
authored
5 *
26499aa @msantos Yeah, this looks legit.
authored
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
a0e301b @msantos spurious trailing whitespace blitz
authored
10 *
26499aa @msantos Yeah, this looks legit.
authored
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
a0e301b @msantos spurious trailing whitespace blitz
authored
15 *
26499aa @msantos Yeah, this looks legit.
authored
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
d972029 @msantos The actual source code ... of a sort
authored
18 *
19 */
20 #include "sods.h"
21 #include "sods_io.h"
22
23 SDS_FWD * sds_io_forward(SDS_STATE *ss, SDS_PKT *pkt);
24
25 int
26 sds_io_write(void *state, void *packet)
27 {
28 SDS_STATE *ss = (SDS_STATE *)state;
29 SDS_PKT *pkt = (SDS_PKT *)packet;
30
31 SDS_CONN *sc = NULL;
32 ssize_t n = 0;
33 ssize_t t = 0;
34
35 #ifdef HAVE_SEND
36 int flags = MSG_NOSIGNAL;
37 #else
38 int flags = 0;
39 #endif
40
41 if ( (sc = sds_q_get(pkt->sess.f.id)) == NULL) {
42 if ( (sc = sds_io_open(ss, pkt)) == NULL) {
43 pkt->err = ns_r_servfail;
44 return (-1);
45 }
46 }
47
48 if (pkt->chksum(ss, sc->sum_up, pkt->sum_up) < 0)
49 return (0);
50
51 while ( (n = send(sc->s, pkt->buf + t, pkt->buflen - t, flags)) != (pkt->buflen - t)) {
52 if (n == -1) {
53 (void)sds_q_del(sc->id);
54 warn("socket send");
55 return (n);
56 }
57 t += n;
58 }
59 sc->sum_up = pkt->sum_up;
60 sc->lastseen = time(NULL);
61
62 return (pkt->buflen);
63 }
64
65 int
66 sds_io_read(void *state, void *packet)
67 {
68 SDS_STATE *ss = (SDS_STATE *)state;
69 SDS_PKT *pkt = (SDS_PKT *)packet;
70
71 SDS_CONN *sc = NULL;
72 ssize_t n = 0;
73
74 if ( (sc = sds_q_get(pkt->sess.f.id)) == NULL) {
75 if ( (sc = sds_io_open(ss, pkt)) == NULL) {
76 pkt->err = ns_r_servfail;
77 return (-1);
78 }
79 }
80
81 if (pkt->chksum(ss, sc->sum, pkt->sum) < 0) {
82 (void)memcpy(pkt->buf, sc->buf, sc->buflen);
83 pkt->buflen = sc->buflen;
84 return (pkt->buflen);
85 }
86
87 sc->lastseen = time(NULL);
88
89 errno = 0;
90 n = read(sc->s, pkt->buf, pkt->nread);
91
92 switch (n) {
93 case -1:
94 switch (errno) {
95 case EAGAIN:
96 n = 0;
97 break;
98 default:
99 (void)sds_q_del(sc->id);
100 warn("socket read");
101 break;
102 }
103 break;
104 case 0:
105 sds_io_close(sc);
106 (void)sds_q_del(sc->id);
107 break;
108 default:
109 sc->buflen = pkt->buflen = n;
110 pkt->sum += n;
111 sc->sum = pkt->sum;
112 (void)memcpy(sc->buf, pkt->buf, pkt->buflen);
113 break;
114 }
115
116 return (n);
117 }
118
119 SDS_CONN *
120 sds_io_open(SDS_STATE *ss, SDS_PKT *pkt)
121 {
122 SDS_CONN *sc = NULL;
123 SDS_FWD *fw = NULL;
124 int flags = 0;
125 #ifdef HAVE_SETSOCKOPT
126 int onoff = 1;
127 #endif /* HAVE_SETSOCKOPT */
128 char src[INET_ADDRSTRLEN];
129 char dst[INET_ADDRSTRLEN];
130
131 if ( (sc = sds_io_alloc(ss, pkt)) == NULL)
132 return (NULL);
133
134 fw = sds_io_forward(ss, pkt);
135
136 sc->sa.sin_family = AF_INET;
137 sc->sa.sin_port = fw->sa.sin_port;
138 sc->sa.sin_addr.s_addr = fw->sa.sin_addr.s_addr;
139
140 VERBOSE(0, "Connecting id = %u, %s:%d -> %s:%d\n", pkt->sess.f.id,
141 inet_ntop(AF_INET, &pkt->sa.sin_addr, src, sizeof(src)),
142 htons(pkt->sa.sin_port),
143 inet_ntop(AF_INET, &sc->sa.sin_addr, dst, sizeof(dst)),
144 htons(sc->sa.sin_port));
145
146 if ( (sc->s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
147 err(EXIT_FAILURE, "socket");
148
149 flags = fcntl(sc->s, F_GETFL, 0);
150 flags |= O_NONBLOCK;
151 (void)fcntl(sc->s, F_SETFL, flags);
152
153 #ifdef HAVE_SETSOCKOPT
154 IS_ERR(setsockopt(sc->s, SOL_SOCKET, SO_NOSIGPIPE, &onoff, sizeof(onoff)));
155 #endif /* HAVE_SETSOCKOPT */
156
157 errno = 0;
158 if (connect(sc->s, (const struct sockaddr *)&sc->sa, sizeof(sc->sa)) < 0) {
159 switch (errno) {
160 case EINPROGRESS:
161 break;
162 case EAGAIN:
163 VERBOSE(0, "no ports available");
164 pkt->err = ns_r_servfail;
165 sds_io_close(sc);
166 (void)sds_q_del(sc->id);
167 return (NULL);
168 break;
169 default:
170 err(EXIT_FAILURE, "connect");
171 }
172 }
173 return (sc);
174 }
175
176 int
177 sds_io_close(void *qe)
178 {
179 SDS_CONN *sc = (SDS_CONN *)qe;
180 (void)shutdown(sc->s, SHUT_RDWR);
181 return (close(sc->s));
182 }
183
184 SDS_CONN *
185 sds_io_alloc(SDS_STATE *ss, SDS_PKT *pkt)
186 {
187 SDS_CONN *sc = NULL;
188
189 if (sds_q_init() < 0)
190 errx(1, "sds_q_init");
191
8d38c71 @msantos Remove useless casts from calloc
authored
192 IS_NULL(sc = calloc(1, sizeof(SDS_CONN)));
d972029 @msantos The actual source code ... of a sort
authored
193
194 sc->id = pkt->sess.f.id;
195 sc->lastseen = time(NULL);
196 sc->close = &sds_io_close;
197
198 if (sds_q_add(ss, sc) < 0) {
199 free (sc);
200 return (NULL);
201 }
202
203 return (sc);
204 }
205
206 SDS_FWD *
207 sds_io_forward(SDS_STATE *ss, SDS_PKT *pkt)
208 {
209 return ( (pkt->sess.f.fwd < ss->fwds) ?
210 (ss->fwd + pkt->sess.f.fwd) :
211 ss->fwd);
212 }
213
Something went wrong with that request. Please try again.