Mercurial > dropbear
comparison listener.c @ 285:1b9e69c058d2
propagate from branch 'au.asn.ucc.matt.ltc.dropbear' (head 20dccfc09627970a312d77fb41dc2970b62689c3)
to branch 'au.asn.ucc.matt.dropbear' (head fdf4a7a3b97ae5046139915de7e40399cceb2c01)
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Wed, 08 Mar 2006 13:23:58 +0000 |
parents | 0cfba3034be5 |
children | 2b4fd440399d |
comparison
equal
deleted
inserted
replaced
281:997e6f7dc01e | 285:1b9e69c058d2 |
---|---|
1 /* | |
2 * Dropbear SSH | |
3 * | |
4 * Copyright (c) 2002,2003 Matt Johnston | |
5 * All rights reserved. | |
6 * | |
7 * Permission is hereby granted, free of charge, to any person obtaining a copy | |
8 * of this software and associated documentation files (the "Software"), to deal | |
9 * in the Software without restriction, including without limitation the rights | |
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
11 * copies of the Software, and to permit persons to whom the Software is | |
12 * furnished to do so, subject to the following conditions: | |
13 * | |
14 * The above copyright notice and this permission notice shall be included in | |
15 * all copies or substantial portions of the Software. | |
16 * | |
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
23 * SOFTWARE. */ | |
24 | |
25 #include "includes.h" | |
26 #include "listener.h" | |
27 #include "session.h" | |
28 #include "dbutil.h" | |
29 | |
30 void listeners_initialise() { | |
31 | |
32 /* just one slot to start with */ | |
33 ses.listeners = (struct Listener**)m_malloc(sizeof(struct Listener*)); | |
34 ses.listensize = 1; | |
35 ses.listeners[0] = NULL; | |
36 | |
37 } | |
38 | |
39 void set_listener_fds(fd_set * readfds) { | |
40 | |
41 unsigned int i, j; | |
42 struct Listener *listener; | |
43 | |
44 /* check each in turn */ | |
45 for (i = 0; i < ses.listensize; i++) { | |
46 listener = ses.listeners[i]; | |
47 if (listener != NULL) { | |
48 for (j = 0; j < listener->nsocks; j++) { | |
49 FD_SET(listener->socks[j], readfds); | |
50 } | |
51 } | |
52 } | |
53 } | |
54 | |
55 | |
56 void handle_listeners(fd_set * readfds) { | |
57 | |
58 unsigned int i, j; | |
59 struct Listener *listener; | |
60 int sock; | |
61 | |
62 /* check each in turn */ | |
63 for (i = 0; i < ses.listensize; i++) { | |
64 listener = ses.listeners[i]; | |
65 if (listener != NULL) { | |
66 for (j = 0; j < listener->nsocks; j++) { | |
67 sock = listener->socks[j]; | |
68 if (FD_ISSET(sock, readfds)) { | |
69 listener->acceptor(listener, sock); | |
70 } | |
71 } | |
72 } | |
73 } | |
74 } /* Woo brace matching */ | |
75 | |
76 | |
77 /* acceptor(int fd, void* typedata) is a function to accept connections, | |
78 * cleanup(void* typedata) happens when cleaning up */ | |
79 struct Listener* new_listener(int socks[], unsigned int nsocks, | |
80 int type, void* typedata, | |
81 void (*acceptor)(struct Listener* listener, int sock), | |
82 void (*cleanup)(struct Listener*)) { | |
83 | |
84 unsigned int i, j; | |
85 struct Listener *newlisten = NULL; | |
86 /* try get a new structure to hold it */ | |
87 for (i = 0; i < ses.listensize; i++) { | |
88 if (ses.listeners[i] == NULL) { | |
89 break; | |
90 } | |
91 } | |
92 | |
93 /* or create a new one */ | |
94 if (i == ses.listensize) { | |
95 if (ses.listensize > MAX_LISTENERS) { | |
96 TRACE(("leave newlistener: too many already")) | |
97 for (j = 0; j < nsocks; j++) { | |
98 close(socks[i]); | |
99 } | |
100 return NULL; | |
101 } | |
102 | |
103 ses.listeners = (struct Listener**)m_realloc(ses.listeners, | |
104 (ses.listensize+LISTENER_EXTEND_SIZE) | |
105 *sizeof(struct Listener*)); | |
106 | |
107 ses.listensize += LISTENER_EXTEND_SIZE; | |
108 | |
109 for (j = i; j < ses.listensize; j++) { | |
110 ses.listeners[j] = NULL; | |
111 } | |
112 } | |
113 | |
114 for (j = 0; j < nsocks; j++) { | |
115 ses.maxfd = MAX(ses.maxfd, socks[j]); | |
116 } | |
117 | |
118 TRACE(("new listener num %d ", i)) | |
119 | |
120 newlisten = (struct Listener*)m_malloc(sizeof(struct Listener)); | |
121 newlisten->index = i; | |
122 newlisten->type = type; | |
123 newlisten->typedata = typedata; | |
124 newlisten->nsocks = nsocks; | |
125 memcpy(newlisten->socks, socks, nsocks * sizeof(int)); | |
126 newlisten->acceptor = acceptor; | |
127 newlisten->cleanup = cleanup; | |
128 | |
129 ses.listeners[i] = newlisten; | |
130 return newlisten; | |
131 } | |
132 | |
133 /* Return the first listener which matches the type-specific comparison | |
134 * function. Particularly needed for global requests, like tcp */ | |
135 struct Listener * get_listener(int type, void* typedata, | |
136 int (*match)(void*, void*)) { | |
137 | |
138 unsigned int i; | |
139 struct Listener* listener; | |
140 | |
141 for (i = 0, listener = ses.listeners[i]; i < ses.listensize; i++) { | |
142 if (listener->type == type | |
143 && match(typedata, listener->typedata)) { | |
144 return listener; | |
145 } | |
146 } | |
147 | |
148 return NULL; | |
149 } | |
150 | |
151 void remove_listener(struct Listener* listener) { | |
152 | |
153 unsigned int j; | |
154 | |
155 if (listener->cleanup) { | |
156 listener->cleanup(listener); | |
157 } | |
158 | |
159 for (j = 0; j < listener->nsocks; j++) { | |
160 close(listener->socks[j]); | |
161 } | |
162 ses.listeners[listener->index] = NULL; | |
163 m_free(listener); | |
164 | |
165 } |