comparison netio.c @ 1464:ad637c9e0f6f

Server chosen tcpfwd ports (#43) Server chosen tcpfwd ports
author houseofkodai <karthik@houseofkodai.in>
date Thu, 25 Jan 2018 19:51:41 +0530
parents 06d52bcb8094
children f7a53832501d
comparison
equal deleted inserted replaced
1463:a3479d0d7e79 1464:ad637c9e0f6f
346 strerror(errno)); 346 strerror(errno));
347 #endif 347 #endif
348 348
349 } 349 }
350 350
351 /* from openssh/canohost.c avoid premature-optimization */
352 int get_sock_port(int sock) {
353 struct sockaddr_storage from;
354 socklen_t fromlen;
355 char strport[NI_MAXSERV];
356 int r;
357
358 /* Get IP address of client. */
359 fromlen = sizeof(from);
360 memset(&from, 0, sizeof(from));
361 if (getsockname(sock, (struct sockaddr *)&from, &fromlen) < 0) {
362 TRACE(("getsockname failed: %d", errno))
363 return 0;
364 }
365
366 /* Work around Linux IPv6 weirdness */
367 if (from.ss_family == AF_INET6)
368 fromlen = sizeof(struct sockaddr_in6);
369
370 /* Non-inet sockets don't have a port number. */
371 if (from.ss_family != AF_INET && from.ss_family != AF_INET6)
372 return 0;
373
374 /* Return port number. */
375 if ((r = getnameinfo((struct sockaddr *)&from, fromlen, NULL, 0,
376 strport, sizeof(strport), NI_NUMERICSERV)) != 0) {
377 TRACE(("netio.c/get_sock_port/getnameinfo NI_NUMERICSERV failed: %d", r))
378 }
379 return atoi(strport);
380 }
381
351 /* Listen on address:port. 382 /* Listen on address:port.
352 * Special cases are address of "" listening on everything, 383 * Special cases are address of "" listening on everything,
353 * and address of NULL listening on localhost only. 384 * and address of NULL listening on localhost only.
354 * Returns the number of sockets bound on success, or -1 on failure. On 385 * Returns the number of sockets bound on success, or -1 on failure. On
355 * failure, if errstring wasn't NULL, it'll be a newly malloced error 386 * failure, if errstring wasn't NULL, it'll be a newly malloced error
398 } 429 }
399 TRACE(("leave dropbear_listen: failed resolving")) 430 TRACE(("leave dropbear_listen: failed resolving"))
400 return -1; 431 return -1;
401 } 432 }
402 433
434 /*
435 * when listening on server-assigned-port 0
436 * the assigned ports may differ for address families (v4/v6)
437 * causing problems for tcpip-forward
438 * caller can do a get_socket_address to discover assigned-port
439 * hence, use same port for all address families
440 */
441 u_int16_t *allocated_lport_p = 0;
442 int allocated_lport = 0;
403 443
404 nsock = 0; 444 nsock = 0;
405 for (res = res0; res != NULL && nsock < sockcount; 445 for (res = res0; res != NULL && nsock < sockcount;
406 res = res->ai_next) { 446 res = res->ai_next) {
447
448 if (allocated_lport > 0) {
449 if (AF_INET == res->ai_family) {
450 allocated_lport_p = &((struct sockaddr_in *)res->ai_addr)->sin_port;
451 } else if (AF_INET6 == res->ai_family) {
452 allocated_lport_p = &((struct sockaddr_in6 *)res->ai_addr)->sin6_port;
453 }
454 *allocated_lport_p = htons(allocated_lport);
455 }
407 456
408 /* Get a socket */ 457 /* Get a socket */
409 socks[nsock] = socket(res->ai_family, res->ai_socktype, 458 socks[nsock] = socket(res->ai_family, res->ai_socktype,
410 res->ai_protocol); 459 res->ai_protocol);
411 460
447 if (listen(sock, DROPBEAR_LISTEN_BACKLOG) < 0) { 496 if (listen(sock, DROPBEAR_LISTEN_BACKLOG) < 0) {
448 err = errno; 497 err = errno;
449 close(sock); 498 close(sock);
450 TRACE(("listen() failed")) 499 TRACE(("listen() failed"))
451 continue; 500 continue;
501 }
502
503 if (0 == allocated_lport) {
504 allocated_lport = get_sock_port(sock);
452 } 505 }
453 506
454 *maxfd = MAX(*maxfd, sock); 507 *maxfd = MAX(*maxfd, sock);
455 508
456 nsock++; 509 nsock++;