diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2006-11-22 16:10:39 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2006-11-22 16:10:39 +0000 |
commit | c8717cd8571cd35d71696aab8aa847169756bd9f (patch) | |
tree | 254a736d3e761bddc4ba4b00a8f6af1d430ad18f /libbb/xconnect.c | |
parent | 0801ef28ca655a28543b28754fd804ba0616c21c (diff) | |
download | busybox-w32-c8717cd8571cd35d71696aab8aa847169756bd9f.tar.gz busybox-w32-c8717cd8571cd35d71696aab8aa847169756bd9f.tar.bz2 busybox-w32-c8717cd8571cd35d71696aab8aa847169756bd9f.zip |
telnetd: move generic stuff into libbb. It will make it easy
to make other server applets IPv6-aware too.
Diffstat (limited to 'libbb/xconnect.c')
-rw-r--r-- | libbb/xconnect.c | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/libbb/xconnect.c b/libbb/xconnect.c index 21ec2761a..cf1f9d59a 100644 --- a/libbb/xconnect.c +++ b/libbb/xconnect.c | |||
@@ -66,3 +66,155 @@ int xconnect_tcp_v4(struct sockaddr_in *s_addr) | |||
66 | xconnect(s, (struct sockaddr*) s_addr, sizeof(*s_addr)); | 66 | xconnect(s, (struct sockaddr*) s_addr, sizeof(*s_addr)); |
67 | return s; | 67 | return s; |
68 | } | 68 | } |
69 | |||
70 | int dotted2sockaddr(const char *dotted, struct sockaddr* sp, int socklen) | ||
71 | { | ||
72 | union { | ||
73 | struct in_addr a4; | ||
74 | #if ENABLE_FEATURE_IPV6 | ||
75 | struct in6_addr a6; | ||
76 | #endif | ||
77 | } a; | ||
78 | |||
79 | /* TODO maybe: port spec? like n.n.n.n:nn */ | ||
80 | |||
81 | #if ENABLE_FEATURE_IPV6 | ||
82 | if (socklen >= sizeof(struct sockaddr_in6) | ||
83 | && inet_pton(AF_INET6, dotted, &a.a6) > 0 | ||
84 | ) { | ||
85 | ((struct sockaddr_in6*)sp)->sin6_family = AF_INET6; | ||
86 | ((struct sockaddr_in6*)sp)->sin6_addr = a.a6; | ||
87 | /* ((struct sockaddr_in6*)sp)->sin6_port = */ | ||
88 | return 0; /* success */ | ||
89 | } | ||
90 | #endif | ||
91 | if (socklen >= sizeof(struct sockaddr_in) | ||
92 | && inet_pton(AF_INET, dotted, &a.a4) > 0 | ||
93 | ) { | ||
94 | ((struct sockaddr_in*)sp)->sin_family = AF_INET; | ||
95 | ((struct sockaddr_in*)sp)->sin_addr = a.a4; | ||
96 | /* ((struct sockaddr_in*)sp)->sin_port = */ | ||
97 | return 0; /* success */ | ||
98 | } | ||
99 | return 1; | ||
100 | } | ||
101 | |||
102 | int xsocket_stream_ip4or6(sa_family_t *fp) | ||
103 | { | ||
104 | int fd; | ||
105 | #if ENABLE_FEATURE_IPV6 | ||
106 | fd = socket(AF_INET6, SOCK_STREAM, 0); | ||
107 | if (fp) *fp = AF_INET6; | ||
108 | if (fd < 0) | ||
109 | #endif | ||
110 | { | ||
111 | fd = xsocket(AF_INET, SOCK_STREAM, 0); | ||
112 | if (fp) *fp = AF_INET; | ||
113 | } | ||
114 | return fd; | ||
115 | } | ||
116 | |||
117 | int create_and_bind_socket_ip4or6(const char *hostaddr, int port) | ||
118 | { | ||
119 | static const int on = 1; | ||
120 | int fd; | ||
121 | sockaddr_inet sa; | ||
122 | |||
123 | memset(&sa, 0, sizeof(sa)); | ||
124 | if (hostaddr && dotted2sockaddr(hostaddr, &sa.sa, sizeof(sa))) | ||
125 | bb_show_usage(); | ||
126 | |||
127 | if (!sa.sa.sa_family) | ||
128 | fd = xsocket_stream_ip4or6(&sa.sa.sa_family); | ||
129 | else /* user specified bind addr dictates family */ | ||
130 | fd = xsocket(sa.sa.sa_family, SOCK_STREAM, 0); | ||
131 | setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); | ||
132 | |||
133 | /* if (port >= 0) { */ | ||
134 | #if ENABLE_FEATURE_IPV6 | ||
135 | if (sa.sa.sa_family == AF_INET6 /* && !sa.sin6.sin6_port */) | ||
136 | sa.sin6.sin6_port = htons(port); | ||
137 | #endif | ||
138 | if (sa.sa.sa_family == AF_INET /* && !sa.sin.sin_port */) | ||
139 | sa.sin.sin_port = htons(port); | ||
140 | /* } */ | ||
141 | |||
142 | xbind(fd, &sa.sa, sizeof(sa)); | ||
143 | return fd; | ||
144 | } | ||
145 | |||
146 | int dotted2sockaddr(const char *dotted, struct sockaddr* sp, int socklen) | ||
147 | { | ||
148 | union { | ||
149 | struct in_addr a4; | ||
150 | #if ENABLE_FEATURE_IPV6 | ||
151 | struct in6_addr a6; | ||
152 | #endif | ||
153 | } a; | ||
154 | |||
155 | /* TODO maybe: port spec? like n.n.n.n:nn */ | ||
156 | |||
157 | #if ENABLE_FEATURE_IPV6 | ||
158 | if (socklen >= sizeof(struct sockaddr_in6) | ||
159 | && inet_pton(AF_INET6, dotted, &a.a6) > 0 | ||
160 | ) { | ||
161 | ((struct sockaddr_in6*)sp)->sin6_family = AF_INET6; | ||
162 | ((struct sockaddr_in6*)sp)->sin6_addr = a.a6; | ||
163 | /* ((struct sockaddr_in6*)sp)->sin6_port = */ | ||
164 | return 0; /* success */ | ||
165 | } | ||
166 | #endif | ||
167 | if (socklen >= sizeof(struct sockaddr_in) | ||
168 | && inet_pton(AF_INET, dotted, &a.a4) > 0 | ||
169 | ) { | ||
170 | ((struct sockaddr_in*)sp)->sin_family = AF_INET; | ||
171 | ((struct sockaddr_in*)sp)->sin_addr = a.a4; | ||
172 | /* ((struct sockaddr_in*)sp)->sin_port = */ | ||
173 | return 0; /* success */ | ||
174 | } | ||
175 | return 1; | ||
176 | } | ||
177 | |||
178 | int xsocket_stream_ip4or6(sa_family_t *fp) | ||
179 | { | ||
180 | int fd; | ||
181 | #if ENABLE_FEATURE_IPV6 | ||
182 | fd = socket(AF_INET6, SOCK_STREAM, 0); | ||
183 | if (fp) *fp = AF_INET6; | ||
184 | if (fd < 0) | ||
185 | #endif | ||
186 | { | ||
187 | fd = xsocket(AF_INET, SOCK_STREAM, 0); | ||
188 | if (fp) *fp = AF_INET; | ||
189 | } | ||
190 | return fd; | ||
191 | } | ||
192 | |||
193 | int create_and_bind_socket_ip4or6(const char *hostaddr, int port) | ||
194 | { | ||
195 | static const int on = 1; | ||
196 | int fd; | ||
197 | sockaddr_inet sa; | ||
198 | |||
199 | memset(&sa, 0, sizeof(sa)); | ||
200 | if (hostaddr) { | ||
201 | if (dotted2sockaddr(hostaddr, &sa.sa, sizeof(sa))) | ||
202 | bb_error_msg_and_die("bad address '%s'", hostaddr); | ||
203 | /* user specified bind addr dictates family */ | ||
204 | fd = xsocket(sa.sa.sa_family, SOCK_STREAM, 0); | ||
205 | } else | ||
206 | fd = xsocket_stream_ip4or6(&sa.sa.sa_family); | ||
207 | setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); | ||
208 | |||
209 | /* if (port >= 0) { */ | ||
210 | #if ENABLE_FEATURE_IPV6 | ||
211 | if (sa.sa.sa_family == AF_INET6 /* && !sa.sin6.sin6_port */) | ||
212 | sa.sin6.sin6_port = htons(port); | ||
213 | #endif | ||
214 | if (sa.sa.sa_family == AF_INET /* && !sa.sin.sin_port */) | ||
215 | sa.sin.sin_port = htons(port); | ||
216 | /* } */ | ||
217 | |||
218 | xbind(fd, &sa.sa, sizeof(sa)); | ||
219 | return fd; | ||
220 | } | ||