├── .gitignore
├── README.md
├── COPYRIGHT
├── Makefile
├── wrapsrv.1
├── wrapsrv.docbook
├── list.h
├── wrapsrv.c
└── LICENSE
/.gitignore:
--------------------------------------------------------------------------------
1 | wrapsrv
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | DNS SRV record command line wrapper
2 | -----------------------------------
3 |
4 | wrapsrv adds support for connecting to a network service based on DNS SRV
5 | record lookups to commands that do not support the DNS SRV record. wrapsrv
6 | implements the weighted priority client connection algorithm in [RFC
7 | 2782](http://tools.ietf.org/html/rfc2782). The specified command line will
8 | be invoked one or more times with %h and %p sequences in the command line
9 | substituted for the hostname and port elements of the selected SRV record.
10 |
--------------------------------------------------------------------------------
/COPYRIGHT:
--------------------------------------------------------------------------------
1 | Copyright (c) 2009-2014 by Farsight Security, Inc.
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | CC = gcc
2 | WARN = -Wall -Wextra -Werror
3 | CFLAGS = -O2 -g $(WARN)
4 | INCLUDE =
5 | LDFLAGS = -lresolv
6 | DESTDIR ?=
7 | PREFIX = /usr/local
8 |
9 | BINDIR ?= $(DESTDIR)$(PREFIX)/bin
10 | MANDIR ?= $(DESTDIR)$(PREFIX)/share/man/man1
11 |
12 | BIN = wrapsrv
13 | MAN = wrapsrv.1
14 | SRC = wrapsrv.c
15 |
16 | all: $(BIN) $(DOC)
17 |
18 | $(BIN): $(SRC)
19 | $(CC) $(CFLAGS) -o $@ $(SRC) $(INCLUDE) $(LDFLAGS)
20 |
21 | $(MAN): wrapsrv.docbook
22 | docbook2x-man $<
23 |
24 | clean:
25 | rm -f $(BIN)
26 |
27 | install: $(BIN)
28 | mkdir -p $(BINDIR)
29 | mkdir -p $(MANDIR)
30 | install -m 0755 $(BIN) $(BINDIR)
31 | install -m 0644 $(MAN) $(MANDIR)
32 |
33 | .PHONY: all clean install
34 |
--------------------------------------------------------------------------------
/wrapsrv.1:
--------------------------------------------------------------------------------
1 | '\" -*- coding: us-ascii -*-
2 | .if \n(.g .ds T< \\FC
3 | .if \n(.g .ds T> \\F[\n[.fam]]
4 | .de URL
5 | \\$2 \(la\\$1\(ra\\$3
6 | ..
7 | .if \n(.g .mso www.tmac
8 | .TH wrapsrv 1 "13 December 2013" "" ""
9 | .SH NAME
10 | wrapsrv \- DNS SRV record command line wrapper
11 | .SH SYNOPSIS
12 | 'nh
13 | .fi
14 | .ad l
15 | \fBwrapsrv\fR \kx
16 | .if (\nx>(\n(.l/2)) .nr x (\n(.l/5)
17 | 'in \n(.iu+\nxu
18 | [\fISRVNAME\fR] [\fICOMMAND\fR] [\fIOPTION\fR]\&...
19 | 'in \n(.iu-\nxu
20 | .ad b
21 | 'hy
22 | .SH DESCRIPTION
23 | \fBwrapsrv\fR adds support for connecting to a
24 | network service based on DNS SRV record lookups to commands that
25 | do not support the DNS SRV record. \fBwrapsrv\fR
26 | implements the weighted priority client connection algorithm in
27 | RFC 2782. The specified command line will be invoked one or more
28 | times with \fI%h\fR and
29 | \fI%p\fR sequences in the command line
30 | substituted for the hostname and port elements of the selected SRV
31 | record. The command line invoked must exit and return 0 after a
32 | successful connection or exit and return non-zero if the
33 | connection fails. \fBwrapsrv\fR will itself exit with
34 | the return code of the last command line invocation, or it may
35 | exit with a non-zero return code if the DNS SRV record lookup
36 | fails for any reason.
37 |
--------------------------------------------------------------------------------
/wrapsrv.docbook:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 | wrapsrv
8 | 1
9 |
10 |
11 |
12 | wrapsrv
13 | DNS SRV record command line wrapper
14 |
15 |
16 |
17 |
18 | wrapsrv
19 | SRVNAME
20 | COMMAND
21 | OPTION
22 |
23 |
24 |
25 |
26 | DESCRIPTION
27 |
28 | wrapsrv adds support for connecting to a
29 | network service based on DNS SRV record lookups to commands that
30 | do not support the DNS SRV record. wrapsrv
31 | implements the weighted priority client connection algorithm in
32 | RFC 2782. The specified command line will be invoked one or more
33 | times with %h and
34 | %p sequences in the command line
35 | substituted for the hostname and port elements of the selected SRV
36 | record. The command line invoked must exit and return 0 after a
37 | successful connection or exit and return non-zero if the
38 | connection fails. wrapsrv will itself exit with
39 | the return code of the last command line invocation, or it may
40 | exit with a non-zero return code if the DNS SRV record lookup
41 | fails for any reason.
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/list.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2004, 2006, 2007 Internet Systems Consortium, Inc. ("ISC")
3 | * Copyright (C) 1997-2002 Internet Software Consortium.
4 | *
5 | * Permission to use, copy, modify, and/or distribute this software for any
6 | * purpose with or without fee is hereby granted, provided that the above
7 | * copyright notice and this permission notice appear in all copies.
8 | *
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 | * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 | * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 | * PERFORMANCE OF THIS SOFTWARE.
16 | */
17 |
18 | #ifndef ISC_LIST_H
19 | #define ISC_LIST_H 1
20 |
21 | #define ISC_INSIST(x) assert(x)
22 | #define ISC_LINK_INSIST(x) assert(x)
23 |
24 | #define ISC_LIST(type) struct { type *head, *tail; }
25 | #define ISC_LIST_INIT(list) \
26 | do { (list).head = NULL; (list).tail = NULL; } while (0)
27 |
28 | #define ISC_LINK(type) struct { type *prev, *next; }
29 | #define ISC_LINK_INIT_TYPE(elt, link, type) \
30 | do { \
31 | (elt)->link.prev = (type *)(-1); \
32 | (elt)->link.next = (type *)(-1); \
33 | } while (0)
34 | #define ISC_LINK_INIT(elt, link) \
35 | ISC_LINK_INIT_TYPE(elt, link, void)
36 | #define ISC_LINK_LINKED(elt, link) ((void *)((elt)->link.prev) != (void *)(-1))
37 |
38 | #define ISC_LIST_HEAD(list) ((list).head)
39 | #define ISC_LIST_TAIL(list) ((list).tail)
40 | #define ISC_LIST_EMPTY(list) ((list.head) == NULL ? 1 : 0)
41 |
42 | #define __ISC_LIST_PREPENDUNSAFE(list, elt, link) \
43 | do { \
44 | if ((list).head != NULL) \
45 | (list).head->link.prev = (elt); \
46 | else \
47 | (list).tail = (elt); \
48 | (elt)->link.prev = NULL; \
49 | (elt)->link.next = (list).head; \
50 | (list).head = (elt); \
51 | } while (0)
52 |
53 | #define ISC_LIST_PREPEND(list, elt, link) \
54 | do { \
55 | ISC_LINK_INSIST(!ISC_LINK_LINKED(elt, link)); \
56 | __ISC_LIST_PREPENDUNSAFE(list, elt, link); \
57 | } while (0)
58 |
59 | #define ISC_LIST_INITANDPREPEND(list, elt, link) \
60 | __ISC_LIST_PREPENDUNSAFE(list, elt, link)
61 |
62 | #define __ISC_LIST_APPENDUNSAFE(list, elt, link) \
63 | do { \
64 | if ((list).tail != NULL) \
65 | (list).tail->link.next = (elt); \
66 | else \
67 | (list).head = (elt); \
68 | (elt)->link.prev = (list).tail; \
69 | (elt)->link.next = NULL; \
70 | (list).tail = (elt); \
71 | } while (0)
72 |
73 | #define ISC_LIST_APPEND(list, elt, link) \
74 | do { \
75 | ISC_LINK_INSIST(!ISC_LINK_LINKED(elt, link)); \
76 | __ISC_LIST_APPENDUNSAFE(list, elt, link); \
77 | } while (0)
78 |
79 | #define ISC_LIST_INITANDAPPEND(list, elt, link) \
80 | __ISC_LIST_APPENDUNSAFE(list, elt, link)
81 |
82 | #define __ISC_LIST_UNLINKUNSAFE_TYPE(list, elt, link, type) \
83 | do { \
84 | if ((elt)->link.next != NULL) \
85 | (elt)->link.next->link.prev = (elt)->link.prev; \
86 | else { \
87 | ISC_INSIST((list).tail == (elt)); \
88 | (list).tail = (elt)->link.prev; \
89 | } \
90 | if ((elt)->link.prev != NULL) \
91 | (elt)->link.prev->link.next = (elt)->link.next; \
92 | else { \
93 | ISC_INSIST((list).head == (elt)); \
94 | (list).head = (elt)->link.next; \
95 | } \
96 | (elt)->link.prev = (type *)(-1); \
97 | (elt)->link.next = (type *)(-1); \
98 | } while (0)
99 |
100 | #define __ISC_LIST_UNLINKUNSAFE(list, elt, link) \
101 | __ISC_LIST_UNLINKUNSAFE_TYPE(list, elt, link, void)
102 |
103 | #define ISC_LIST_UNLINK_TYPE(list, elt, link, type) \
104 | do { \
105 | ISC_LINK_INSIST(ISC_LINK_LINKED(elt, link)); \
106 | __ISC_LIST_UNLINKUNSAFE_TYPE(list, elt, link, type); \
107 | } while (0)
108 | #define ISC_LIST_UNLINK(list, elt, link) \
109 | ISC_LIST_UNLINK_TYPE(list, elt, link, void)
110 |
111 | #define ISC_LIST_PREV(elt, link) ((elt)->link.prev)
112 | #define ISC_LIST_NEXT(elt, link) ((elt)->link.next)
113 |
114 | #define __ISC_LIST_INSERTBEFOREUNSAFE(list, before, elt, link) \
115 | do { \
116 | if ((before)->link.prev == NULL) \
117 | ISC_LIST_PREPEND(list, elt, link); \
118 | else { \
119 | (elt)->link.prev = (before)->link.prev; \
120 | (before)->link.prev = (elt); \
121 | (elt)->link.prev->link.next = (elt); \
122 | (elt)->link.next = (before); \
123 | } \
124 | } while (0)
125 |
126 | #define ISC_LIST_INSERTBEFORE(list, before, elt, link) \
127 | do { \
128 | ISC_LINK_INSIST(ISC_LINK_LINKED(before, link)); \
129 | ISC_LINK_INSIST(!ISC_LINK_LINKED(elt, link)); \
130 | __ISC_LIST_INSERTBEFOREUNSAFE(list, before, elt, link); \
131 | } while (0)
132 |
133 | #define __ISC_LIST_INSERTAFTERUNSAFE(list, after, elt, link) \
134 | do { \
135 | if ((after)->link.next == NULL) \
136 | ISC_LIST_APPEND(list, elt, link); \
137 | else { \
138 | (elt)->link.next = (after)->link.next; \
139 | (after)->link.next = (elt); \
140 | (elt)->link.next->link.prev = (elt); \
141 | (elt)->link.prev = (after); \
142 | } \
143 | } while (0)
144 |
145 | #define ISC_LIST_INSERTAFTER(list, after, elt, link) \
146 | do { \
147 | ISC_LINK_INSIST(ISC_LINK_LINKED(after, link)); \
148 | ISC_LINK_INSIST(!ISC_LINK_LINKED(elt, link)); \
149 | __ISC_LIST_INSERTAFTERUNSAFE(list, after, elt, link); \
150 | } while (0)
151 |
152 | #define ISC_LIST_APPENDLIST(list1, list2, link) \
153 | do { \
154 | if (ISC_LIST_EMPTY(list1)) \
155 | (list1) = (list2); \
156 | else if (!ISC_LIST_EMPTY(list2)) { \
157 | (list1).tail->link.next = (list2).head; \
158 | (list2).head->link.prev = (list1).tail; \
159 | (list1).tail = (list2).tail; \
160 | } \
161 | (list2).head = NULL; \
162 | (list2).tail = NULL; \
163 | } while (0)
164 |
165 | #define ISC_LIST_ENQUEUE(list, elt, link) ISC_LIST_APPEND(list, elt, link)
166 | #define __ISC_LIST_ENQUEUEUNSAFE(list, elt, link) \
167 | __ISC_LIST_APPENDUNSAFE(list, elt, link)
168 | #define ISC_LIST_DEQUEUE(list, elt, link) \
169 | ISC_LIST_UNLINK_TYPE(list, elt, link, void)
170 | #define ISC_LIST_DEQUEUE_TYPE(list, elt, link, type) \
171 | ISC_LIST_UNLINK_TYPE(list, elt, link, type)
172 | #define __ISC_LIST_DEQUEUEUNSAFE(list, elt, link) \
173 | __ISC_LIST_UNLINKUNSAFE_TYPE(list, elt, link, void)
174 | #define __ISC_LIST_DEQUEUEUNSAFE_TYPE(list, elt, link, type) \
175 | __ISC_LIST_UNLINKUNSAFE_TYPE(list, elt, link, type)
176 |
177 | #endif /* ISC_LIST_H */
178 |
--------------------------------------------------------------------------------
/wrapsrv.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2009, 2011, 2014 by Farsight Security, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | /* Import. */
18 |
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 |
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include
34 | #include
35 |
36 | #include "list.h"
37 |
38 | #ifndef NS_MAXMSG
39 | #define NS_MAXMSG 65535
40 | #endif
41 |
42 | /* Data types. */
43 |
44 | struct srv {
45 | ISC_LINK(struct srv) link;
46 | char *tname;
47 | uint16_t weight;
48 | uint16_t port;
49 | };
50 |
51 | struct srv_prio {
52 | ISC_LINK(struct srv_prio) link;
53 | ISC_LIST(struct srv) srv_list;
54 | uint16_t prio;
55 | };
56 |
57 | typedef ISC_LIST(struct srv) srv_list;
58 | typedef ISC_LIST(struct srv_prio) srv_prio_list;
59 |
60 | /* Globals. */
61 |
62 | static srv_prio_list prio_list;
63 |
64 | /* Forward. */
65 |
66 | static char *subst_cmd(struct srv *, const char *);
67 | static char *target_name(const unsigned char *);
68 | static int do_cmd(struct srv *, int, char **);
69 | static struct srv *next_tuple(void);
70 | static void free_tuples(void);
71 | static void insert_tuple(char *, uint16_t, uint16_t, uint16_t);
72 | static void parse_answer_section(ns_msg *);
73 | static void usage(void);
74 |
75 | #ifdef DEBUG
76 | static void print_tuples(void);
77 | #endif
78 |
79 | /* Functions. */
80 |
81 | static struct srv *
82 | next_tuple(void) {
83 | struct srv_prio *pe;
84 | struct srv *se;
85 | uint16_t rnd;
86 | unsigned csum = 0;
87 | unsigned wsum = 0;
88 |
89 | pe = ISC_LIST_HEAD(prio_list);
90 | if (pe == NULL)
91 | return (NULL);
92 |
93 | for (se = ISC_LIST_HEAD(pe->srv_list);
94 | se != NULL;
95 | se = ISC_LIST_NEXT(se, link))
96 | {
97 | wsum += se->weight;
98 | }
99 |
100 | rnd = random() % (wsum + 1);
101 |
102 | for (se = ISC_LIST_HEAD(pe->srv_list);
103 | se != NULL;
104 | se = ISC_LIST_NEXT(se, link))
105 | {
106 | csum += se->weight;
107 |
108 | if (csum >= rnd) {
109 | ISC_LIST_UNLINK(pe->srv_list, se, link);
110 | break;
111 | }
112 | }
113 |
114 | if (se == NULL) {
115 | ISC_LIST_UNLINK(prio_list, pe, link);
116 | free(pe);
117 | return (next_tuple());
118 | }
119 |
120 | #ifdef DEBUG
121 | fprintf(stderr, "rnd=%hu -> prio=%hu weight=%hu port=%hu tname=%s\n",
122 | rnd, pe->prio, se->weight, se->port, se->tname);
123 | #endif
124 |
125 | return (se);
126 | }
127 |
128 | static void
129 | free_tuples(void) {
130 | struct srv_prio *pe, *pe_next;
131 | struct srv *se, *se_next;
132 |
133 | pe = ISC_LIST_HEAD(prio_list);
134 | while (pe != NULL) {
135 | pe_next = ISC_LIST_NEXT(pe, link);
136 | ISC_LIST_UNLINK(prio_list, pe, link);
137 |
138 | se = ISC_LIST_HEAD(pe->srv_list);
139 | while (se != NULL) {
140 | se_next = ISC_LIST_NEXT(se, link);
141 | ISC_LIST_UNLINK(pe->srv_list, se, link);
142 | free(se->tname);
143 | free(se);
144 | se = se_next;
145 | }
146 |
147 | free(pe);
148 | pe = pe_next;
149 | }
150 | }
151 |
152 | static void
153 | insert_tuple(char *tname, uint16_t prio, uint16_t weight, uint16_t port) {
154 | struct srv_prio *pe;
155 | struct srv *se;
156 |
157 | for (pe = ISC_LIST_HEAD(prio_list);
158 | pe != NULL;
159 | pe = ISC_LIST_NEXT(pe, link))
160 | {
161 | if (pe->prio == prio)
162 | break;
163 | }
164 |
165 | if (pe == NULL) {
166 | struct srv_prio *piter;
167 |
168 | pe = malloc(sizeof(*pe));
169 | assert(pe != NULL);
170 |
171 | ISC_LINK_INIT(pe, link);
172 | ISC_LIST_INIT(pe->srv_list);
173 | pe->prio = prio;
174 |
175 | for (piter = ISC_LIST_HEAD(prio_list);
176 | piter != NULL;
177 | piter = ISC_LIST_NEXT(piter, link))
178 | {
179 | assert(piter->prio != prio);
180 |
181 | if (piter->prio > prio) {
182 | ISC_LIST_INSERTBEFORE(prio_list, piter, pe, link);
183 | break;
184 | }
185 | }
186 |
187 | if (piter == NULL)
188 | ISC_LIST_APPEND(prio_list, pe, link);
189 | }
190 |
191 | se = malloc(sizeof(*se));
192 | assert(se != NULL);
193 |
194 | ISC_LINK_INIT(se, link);
195 | se->tname = tname;
196 | se->weight = weight;
197 | se->port = port;
198 |
199 | ISC_LIST_APPEND(pe->srv_list, se, link);
200 | }
201 |
202 | #ifdef DEBUG
203 | static void
204 | print_tuples(void) {
205 | struct srv_prio *pe;
206 | struct srv *se;
207 |
208 | for (pe = ISC_LIST_HEAD(prio_list);
209 | pe != NULL;
210 | pe = ISC_LIST_NEXT(pe, link))
211 | {
212 | fprintf(stderr, "prio=%hu\n", pe->prio);
213 | for (se = ISC_LIST_HEAD(pe->srv_list);
214 | se != NULL;
215 | se = ISC_LIST_NEXT(se, link))
216 | {
217 | fprintf(stderr, "\tweight=%hu port=%hu tname=%s\n",
218 | se->weight, se->port, se->tname);
219 | }
220 | }
221 | }
222 | #endif
223 |
224 | static char *
225 | target_name(const unsigned char *target) {
226 | char buf[NS_MAXDNAME];
227 |
228 | if (ns_name_ntop(target, buf, sizeof buf) == -1) {
229 | perror("ns_name_ntop");
230 | exit(EXIT_FAILURE);
231 | }
232 | return (strdup(buf));
233 | }
234 |
235 | static void
236 | parse_answer_section(ns_msg *msg) {
237 | int rrnum, rrmax;
238 | ns_rr rr;
239 | uint16_t prio, weight, port, len;
240 | const unsigned char *rdata;
241 | char *tname;
242 |
243 | rrmax = ns_msg_count(*msg, ns_s_an);
244 | for (rrnum = 0; rrnum < rrmax; rrnum++) {
245 | if (ns_parserr(msg, ns_s_an, rrnum, &rr)) {
246 | perror("ns_parserr");
247 | exit(EXIT_FAILURE);
248 | }
249 | if (ns_rr_type(rr) == ns_t_srv) {
250 | len = ns_rr_rdlen(rr);
251 | rdata = ns_rr_rdata(rr);
252 | if (len > 3U * NS_INT16SZ) {
253 | NS_GET16(prio, rdata);
254 | NS_GET16(weight, rdata);
255 | NS_GET16(port, rdata);
256 | len -= 3U * NS_INT16SZ;
257 | tname = target_name(rdata);
258 | insert_tuple(tname, prio, weight, port);
259 | }
260 | }
261 | }
262 | }
263 |
264 | static char *
265 | subst_cmd(struct srv *se, const char *cmd) {
266 | char *q, *str;
267 | const char *p = cmd;
268 | int ch;
269 | int n_host = 0;
270 | int n_port = 0;
271 | size_t bufsz;
272 | size_t len_tname;
273 |
274 | len_tname = strlen(se->tname);
275 |
276 | while ((ch = *p++) != '\0') {
277 | if (ch == '%' && *p == 'h')
278 | n_host++;
279 | if (ch == '%' && *p == 'p')
280 | n_port++;
281 | }
282 |
283 | bufsz = strlen(cmd) + 1;
284 | bufsz -= 2 * (n_host + n_port); /* '%h' and '%p' */
285 | bufsz += 5 * n_port; /* '%h' -> uint16_t */
286 | bufsz += (strlen(se->tname) + 1) * n_host;
287 |
288 | str = calloc(1, bufsz);
289 | assert(str != NULL);
290 |
291 | p = cmd;
292 | q = str;
293 | while ((ch = *p++) != '\0') {
294 | if (ch == '%' && *p == 'h') {
295 | strcpy(q, se->tname);
296 | q += len_tname;
297 | p++;
298 | } else if (ch == '%' && *p == 'p') {
299 | q += sprintf(q, "%hu", se->port);
300 | p++;
301 | } else {
302 | *q++ = ch;
303 | }
304 | }
305 |
306 | return (str);
307 | }
308 |
309 | static int
310 | do_cmd(struct srv *se, int argc, char **argv) {
311 | char *cmd, *scmd, *p;
312 | int i, rc;
313 | size_t bufsz = 2;
314 |
315 | for (i = 2; i < argc; i++) {
316 | bufsz += 1;
317 | bufsz += strlen(argv[i]);
318 | }
319 |
320 | p = cmd = malloc(bufsz);
321 | assert(cmd != NULL);
322 |
323 | for (i = 2; i < argc; i++) {
324 | strcpy(p, argv[i]);
325 | p += strlen(argv[i]);
326 | if (i != argc - 1) {
327 | *p++ = ' ';
328 | }
329 | }
330 |
331 | scmd = subst_cmd(se, cmd);
332 | free(cmd);
333 |
334 | #ifdef DEBUG
335 | fprintf(stderr, "scmd='%s'\n", scmd);
336 | #endif
337 |
338 | rc = system(scmd);
339 | rc = WEXITSTATUS(rc);
340 |
341 | free(scmd);
342 | free(se->tname);
343 | free(se);
344 |
345 | #ifdef DEBUG
346 | fprintf(stderr, "rc=%i\n", rc);
347 | #endif
348 | return (rc);
349 | }
350 |
351 | static void
352 | usage(void) {
353 | fprintf(stderr, "Usage: wrapsrv [OPTION]...\n");
354 | fprintf(stderr, "%%h and %%p sequences will be converted to "
355 | "hostname and port.\n");
356 | exit(EXIT_FAILURE);
357 | }
358 |
359 | int
360 | main(int argc, char **argv) {
361 | char *qname;
362 | ns_msg msg;
363 | int len, rc = 0;
364 | unsigned char answer[NS_MAXMSG];
365 | unsigned rcode;
366 | struct srv *se;
367 | struct timeval tv;
368 | unsigned int seed = 0;
369 |
370 | if (argc < 3)
371 | usage();
372 |
373 | ISC_LIST_INIT(prio_list);
374 |
375 | gettimeofday(&tv, NULL);
376 |
377 | seed ^= (unsigned int) tv.tv_usec;
378 | seed ^= (unsigned int) getpid();
379 |
380 | srandom(seed);
381 |
382 | res_init();
383 |
384 | qname = argv[1];
385 |
386 | len = res_query(qname, ns_c_in, ns_t_srv, answer, sizeof answer);
387 | if (len < 0) {
388 | herror("res_query");
389 | return (EXIT_FAILURE);
390 | }
391 |
392 | if (ns_initparse(answer, len, &msg) < 0) {
393 | perror("ns_initparse");
394 | return (EXIT_FAILURE);
395 | }
396 |
397 | rcode = ns_msg_getflag(msg, ns_f_rcode);
398 | if (rcode != ns_r_noerror) {
399 | fprintf(stderr, "wrapsrv: query for %s returned rcode %u\n",
400 | qname, rcode);
401 | return (EXIT_FAILURE);
402 | }
403 |
404 | if (ns_msg_count(msg, ns_s_an) == 0) {
405 | fprintf(stderr, "wrapsrv: query for %s returned no answers\n",
406 | qname);
407 | return (EXIT_FAILURE);
408 | }
409 |
410 | parse_answer_section(&msg);
411 | #ifdef DEBUG
412 | print_tuples();
413 | fprintf(stderr, "\n");
414 | #endif
415 |
416 | while ((se = next_tuple()) != NULL) {
417 | if ((rc = do_cmd(se, argc, argv)) == 0)
418 | break;
419 | #ifdef DEBUG
420 | fprintf(stderr, "\n");
421 | #endif
422 | }
423 |
424 | free_tuples();
425 |
426 | return (rc);
427 | }
428 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------