00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "P_Net.h"
00029
00030 #define SET_NO_LINGER
00031
00032
00033
00034 #define FIRST_RANDOM_PORT 16000
00035 #define LAST_RANDOM_PORT 32000
00036
00037 #define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y))
00038
00039 #if TS_USE_TPROXY
00040 #if !defined(IP_TRANSPARENT)
00041 unsigned int const IP_TRANSPARENT = 19;
00042 #endif
00043 #endif
00044
00045
00046
00047
00048 int
00049 Connection::setup_mc_send(
00050 sockaddr const* mc_addr,
00051 sockaddr const* my_addr,
00052 bool non_blocking, unsigned char mc_ttl, bool mc_loopback, Continuation * c
00053 ) {
00054 (void) c;
00055 ink_assert(fd == NO_FD);
00056 int res = 0;
00057 int enable_reuseaddr = 1;
00058 in_addr_t mc_if = ats_ip4_addr_cast(my_addr);
00059
00060 if ((res = socketManager.mc_socket(my_addr->sa_family, SOCK_DGRAM, 0, non_blocking)) < 0)
00061 goto Lerror;
00062
00063 fd = res;
00064
00065 if ((res = safe_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &enable_reuseaddr, sizeof(enable_reuseaddr)) < 0)) {
00066 goto Lerror;
00067 }
00068
00069 if ((res = socketManager.ink_bind(fd, my_addr, ats_ip_size(my_addr), IPPROTO_UDP)) < 0) {
00070 goto Lerror;
00071 }
00072
00073 ats_ip_copy(&addr, mc_addr);
00074
00075 #ifdef SET_CLOSE_ON_EXEC
00076 if ((res = safe_fcntl(fd, F_SETFD, 1)) < 0)
00077 goto Lerror;
00078 #endif
00079
00080 if (non_blocking)
00081 if ((res = safe_nonblocking(fd)) < 0)
00082 goto Lerror;
00083
00084
00085 if ((res = safe_setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, (char *) &mc_ttl, sizeof(mc_ttl)) < 0))
00086 goto Lerror;
00087
00088
00089 if ((res = safe_setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, (char *) &mc_if, sizeof(mc_if)) < 0))
00090 goto Lerror;
00091
00092
00093 if (!mc_loopback) {
00094 char loop = 0;
00095
00096 if ((res = safe_setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, (char *) &loop, sizeof(loop)) < 0))
00097 goto Lerror;
00098 }
00099 return 0;
00100
00101 Lerror:
00102 if (fd != NO_FD)
00103 close();
00104 return res;
00105 }
00106
00107
00108 int
00109 Connection::setup_mc_receive(
00110 sockaddr const* mc_addr,
00111 sockaddr const* my_addr,
00112 bool non_blocking, Connection * sendChan, Continuation * c
00113 ) {
00114 ink_assert(fd == NO_FD);
00115 (void) sendChan;
00116 (void) c;
00117 int res = 0;
00118 int enable_reuseaddr = 1;
00119 IpAddr inaddr_any(INADDR_ANY);
00120
00121 if ((res = socketManager.socket(mc_addr->sa_family, SOCK_DGRAM, 0)) < 0)
00122 goto Lerror;
00123
00124 fd = res;
00125
00126 #ifdef SET_CLOSE_ON_EXEC
00127 if ((res = safe_fcntl(fd, F_SETFD, 1)) < 0)
00128 goto Lerror;
00129 #endif
00130
00131 if ((res = safe_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &enable_reuseaddr, sizeof(enable_reuseaddr)) < 0))
00132 goto Lerror;
00133
00134 addr.assign(inaddr_any, ats_ip_port_cast(mc_addr));
00135
00136 if ((res = socketManager.ink_bind(fd, &addr.sa, ats_ip_size(&addr.sa), IPPROTO_TCP)) < 0)
00137 goto Lerror;
00138
00139 if (non_blocking)
00140 if ((res = safe_nonblocking(fd)) < 0)
00141 goto Lerror;
00142
00143 if (ats_is_ip4(&addr)) {
00144 struct ip_mreq mc_request;
00145
00146 mc_request.imr_multiaddr.s_addr = ats_ip4_addr_cast(mc_addr);
00147 mc_request.imr_interface.s_addr = ats_ip4_addr_cast(my_addr);
00148
00149 if ((res = safe_setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mc_request, sizeof(mc_request)) < 0))
00150 goto Lerror;
00151 }
00152 return 0;
00153
00154 Lerror:
00155 if (fd != NO_FD)
00156 close();
00157 return res;
00158 }
00159
00160 namespace {
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179 cleaner<self> clean_up(this, &self::cleanup);
00180 // modify or check the resource
00181 if (fail) return FAILURE; // cleanup() is called
00182
00183 clean_up.reset(); // cleanup() not called after this
00184 return SUCCESS;
00185 @endcode
00186 */
00187 template <typename T> struct cleaner {
00188 T* obj;
00189 typedef void (T::*method)();
00190 method m;
00191
00192 cleaner(T* _obj, method _method) : obj(_obj), m(_method) {}
00193 ~cleaner() { if (obj) (obj->*m)(); }
00194 void reset() { obj = 0; }
00195 };
00196 }
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215 NetVCOptions const Connection::DEFAULT_OPTIONS;
00216
00217 int
00218 Connection::open(NetVCOptions const& opt)
00219 {
00220 ink_assert(fd == NO_FD);
00221 int enable_reuseaddr = 1;
00222 int res = 0;
00223 IpEndpoint local_addr;
00224 sock_type = NetVCOptions::USE_UDP == opt.ip_proto
00225 ? SOCK_DGRAM
00226 : SOCK_STREAM;
00227 int family;
00228
00229
00230
00231 ink_zero(local_addr);
00232
00233 bool is_any_address = false;
00234 if (NetVCOptions::FOREIGN_ADDR == opt.addr_binding ||
00235 NetVCOptions::INTF_ADDR == opt.addr_binding
00236 ) {
00237
00238
00239
00240 ink_release_assert(opt.local_ip.isValid());
00241 local_addr.assign(opt.local_ip, htons(opt.local_port));
00242 family = opt.local_ip.family();
00243 } else {
00244
00245 family = ats_is_ip(opt.ip_family) ? opt.ip_family : AF_INET;
00246 local_addr.setToAnyAddr(family);
00247 is_any_address = true;
00248 local_addr.port() = htons(opt.local_port);
00249 }
00250
00251 res = socketManager.socket(family, sock_type, 0);
00252 if (-1 == res) return -errno;
00253
00254 fd = res;
00255
00256 cleaner<Connection> cleanup(this, &Connection::_cleanup);
00257
00258
00259
00260 if (-1 == safe_setsockopt(fd,
00261 SOL_SOCKET,
00262 SO_REUSEADDR,
00263 reinterpret_cast<char *>(&enable_reuseaddr),
00264 sizeof(enable_reuseaddr)))
00265 return -errno;
00266
00267 if (NetVCOptions::FOREIGN_ADDR == opt.addr_binding) {
00268 static char const * const DEBUG_TEXT = "::open setsockopt() IP_TRANSPARENT";
00269 #if TS_USE_TPROXY
00270 int value = 1;
00271 if (-1 == safe_setsockopt(fd, SOL_IP, TS_IP_TRANSPARENT,
00272 reinterpret_cast<char*>(&value), sizeof(value)
00273 )) {
00274 Debug("socket", "%s - fail %d:%s", DEBUG_TEXT, errno, strerror(errno));
00275 return -errno;
00276 } else {
00277 Debug("socket", "%s set", DEBUG_TEXT);
00278 }
00279 #else
00280 Debug("socket", "%s - requested but TPROXY not configured", DEBUG_TEXT);
00281 #endif
00282 }
00283
00284 if (!opt.f_blocking_connect && -1 == safe_nonblocking(fd))
00285 return -errno;
00286
00287 if (opt.socket_recv_bufsize > 0) {
00288 if (socketManager.set_rcvbuf_size(fd, opt.socket_recv_bufsize)) {
00289
00290 int rbufsz = ROUNDUP(opt.socket_recv_bufsize, 1024);
00291 while (rbufsz && !socketManager.set_rcvbuf_size(fd, rbufsz))
00292 rbufsz -= 1024;
00293 Debug("socket", "::open: recv_bufsize = %d of %d\n", rbufsz, opt.socket_recv_bufsize);
00294 }
00295 }
00296 if (opt.socket_send_bufsize > 0) {
00297 if (socketManager.set_sndbuf_size(fd, opt.socket_send_bufsize)) {
00298
00299 int sbufsz = ROUNDUP(opt.socket_send_bufsize, 1024);
00300 while (sbufsz && !socketManager.set_sndbuf_size(fd, sbufsz))
00301 sbufsz -= 1024;
00302 Debug("socket", "::open: send_bufsize = %d of %d\n", sbufsz, opt.socket_send_bufsize);
00303 }
00304 }
00305
00306
00307 apply_options(opt);
00308
00309 if(local_addr.port() || !is_any_address) {
00310 if (-1 == socketManager.ink_bind(fd, &local_addr.sa, ats_ip_size(&local_addr.sa)))
00311 return -errno;
00312 }
00313
00314 cleanup.reset();
00315 is_bound = true;
00316 return 0;
00317 }
00318
00319 int
00320 Connection::connect(sockaddr const* target, NetVCOptions const& opt) {
00321 ink_assert(fd != NO_FD);
00322 ink_assert(is_bound);
00323 ink_assert(!is_connected);
00324
00325 int res;
00326
00327 this->setRemote(target);
00328
00329 cleaner<Connection> cleanup(this, &Connection::_cleanup);
00330
00331 res = ::connect(fd, target, ats_ip_size(target));
00332
00333
00334
00335
00336
00337
00338 if (-1 == res
00339 && (opt.f_blocking_connect
00340 || ! (EINPROGRESS == errno || EWOULDBLOCK == errno))) {
00341 return -errno;
00342 } else if (opt.f_blocking_connect && !opt.f_blocking) {
00343 if (-1 == safe_nonblocking(fd)) return -errno;
00344 } else if (!opt.f_blocking_connect && opt.f_blocking) {
00345 if (-1 == safe_blocking(fd)) return -errno;
00346 }
00347
00348 cleanup.reset();
00349 is_connected = true;
00350 return 0;
00351 }
00352
00353 void
00354 Connection::_cleanup()
00355 {
00356 this->close();
00357 }
00358
00359 void
00360 Connection::apply_options(NetVCOptions const& opt)
00361 {
00362
00363
00364 if (SOCK_STREAM == sock_type) {
00365 if (opt.sockopt_flags & NetVCOptions::SOCK_OPT_NO_DELAY) {
00366 safe_setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, SOCKOPT_ON, sizeof(int));
00367 Debug("socket", "::open: setsockopt() TCP_NODELAY on socket");
00368 }
00369 if (opt.sockopt_flags & NetVCOptions::SOCK_OPT_KEEP_ALIVE) {
00370 safe_setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, SOCKOPT_ON, sizeof(int));
00371 Debug("socket", "::open: setsockopt() SO_KEEPALIVE on socket");
00372 }
00373 }
00374
00375 #if TS_HAS_SO_MARK
00376 uint32_t mark = opt.packet_mark;
00377 safe_setsockopt(fd, SOL_SOCKET, SO_MARK, reinterpret_cast<char *>(&mark), sizeof(uint32_t));
00378 #endif
00379
00380 #if TS_HAS_IP_TOS
00381 uint32_t tos = opt.packet_tos;
00382 safe_setsockopt(fd, IPPROTO_IP, IP_TOS, reinterpret_cast<char *>(&tos), sizeof(uint32_t));
00383 #endif
00384
00385 }