int netcat_socket_new_connect(nc_domain_t domain, nc_proto_t proto, const nc_host_t *addr, const nc_port_t *port, const nc_host_t *local_addr, const nc_port_t *local_port, const nc_sockopts_t *opts) { int sock, ret; assert(addr); debug_dv(("netcat_socket_new_connect(domain=%d, addr=%p, port=%hu, " "local_addr=%p, local_port=%hu)", domain, (void *)addr, port->num, (void *)local_addr, local_port->num)); /* create the socket and fix the options */ sock = netcat_socket_new(domain, proto, opts); if (sock < 0) return sock; /* just forward the error code */ /* only if needed, bind it to a local address */ if (local_addr || local_port->num) { ret = netcat_bind(sock, domain, local_addr, local_port); if (ret < 0) { ret = -3; goto err; } } /* add the non-blocking flag to this socket */ if ((ret = fcntl(sock, F_GETFL, 0)) >= 0) ret = fcntl(sock, F_SETFL, ret | O_NONBLOCK); if (ret < 0) { ret = -4; goto err; } /* now launch the real connection. Since we are in non-blocking mode, this call will return -1 in MOST cases (on some systems, a connect() to a local address may immediately return successfully) */ ret = netcat_connect(sock, domain, addr, port); if ((ret < 0) && (errno != EINPROGRESS)) { ret = -5; goto err; } /* everything went fine, return the (connected or connecting) socket */ return sock; err: /* the if () statement is unuseful, but I need to for declaring vars */ if (ret < 0) { int tmpret, saved_errno = errno; /* the close() calls MUST NOT fail */ tmpret = close(sock); assert(tmpret >= 0); /* restore the original errno */ errno = saved_errno; } return ret; }
int netcat_socket_new_listen(int domain, const struct in_addr *addr, in_port_t port) { int sock, ret, my_family; struct sockaddr_in my_addr; debug_dv(("netcat_socket_new_listen(addr=%p, port=%hu)", (void *)addr, port)); /* selects the currently supported domains */ if (domain == PF_INET) my_family = AF_INET; else return -1; /* assumes as the socket(2) call failed */ /* Reset the sockaddr structure */ memset(&my_addr, 0, sizeof(my_addr)); my_addr.sin_family = my_family; my_addr.sin_port = port; /* this parameter is not mandatory. if it's not present, it's assumed as INADDR_ANY, and the behaviour is the same */ if (addr) memcpy(&my_addr.sin_addr, addr, sizeof(my_addr.sin_addr)); /* create the socket and fix the options */ sock = netcat_socket_new(domain, SOCK_STREAM); if (sock < 0) return sock; /* forward the error code */ /* bind it to the specified address (can be INADDY_ANY) */ ret = bind(sock, (struct sockaddr *)&my_addr, sizeof(my_addr)); if (ret < 0) { ret = -3; goto err; } /* now make it listening, with a reasonable backlog value */ ret = listen(sock, 4); if (ret < 0) { ret = -4; goto err; } return sock; err: /* the if () statement is unuseful, but I need to for declaring vars */ if (ret < 0) { int tmpret, saved_errno = errno; /* the close() calls MUST NOT fail */ tmpret = close(sock); assert(tmpret >= 0); /* restore the original errno */ errno = saved_errno; } return ret; }
int netcat_socket_new_listen(nc_domain_t domain, const nc_host_t *addr, const nc_port_t *port, const nc_sockopts_t *opts) { int sock, ret; debug_dv(("netcat_socket_new_listen(addr=%p, port=(%hu))", (void *)addr, port->num)); /* create the socket and fix the options */ sock = netcat_socket_new(domain, NETCAT_PROTO_TCP, opts); if (sock < 0) return sock; /* forward the error code */ /* bind it to the specified address (can be INADDY_ANY) */ ret = netcat_bind(sock, domain, addr, port); if (ret < 0) { ret = -3; goto err; } /* now make it listening, with a reasonable backlog value */ ret = listen(sock, 4); if (ret < 0) { ret = -4; goto err; } return sock; err: /* the `if' statement is unuseful, but I need it to declare vars */ if (ret < 0) { int tmpret, saved_errno = errno; /* the close() calls MUST NOT fail */ tmpret = close(sock); assert(tmpret >= 0); /* restore the original errno */ errno = saved_errno; } return ret; }
static int core_udp_connect(nc_sock_t *ncsock) { int ret, sock; struct sockaddr_in myaddr; debug_v(("core_udp_connect(ncsock=%p)", (void *)ncsock)); sock = netcat_socket_new(PF_INET, SOCK_DGRAM); if (sock < 0) return -1; /* prepare myaddr for the bind() call */ myaddr.sin_family = AF_INET; myaddr.sin_port = ncsock->local_port.netnum; memcpy(&myaddr.sin_addr, &ncsock->local_host.iaddrs[0], sizeof(myaddr.sin_addr)); /* only call bind if it is really needed */ if (myaddr.sin_port || myaddr.sin_addr.s_addr) { ret = bind(sock, (struct sockaddr *)&myaddr, sizeof(myaddr)); if (ret < 0) goto err; } /* now prepare myaddr for the connect() call */ myaddr.sin_family = AF_INET; myaddr.sin_port = ncsock->port.netnum; memcpy(&myaddr.sin_addr, &ncsock->host.iaddrs[0], sizeof(myaddr.sin_addr)); ret = connect(sock, (struct sockaddr *)&myaddr, sizeof(myaddr)); if (ret < 0) goto err; return sock; err: close(sock); return -1; } /* end of core_udp_connect() */
static int core_udp_listen(nc_sock_t *ncsock) { int ret, *sockbuf, sock, sock_max, timeout = ncsock->timeout; bool need_udphelper = TRUE; #ifdef USE_PKTINFO int sockopt = 1; #endif struct sockaddr_in myaddr; struct timeval tt; /* needed by the select() call */ debug_v(("core_udp_listen(ncsock=%p)", (void *)ncsock)); #ifdef USE_PKTINFO need_udphelper = FALSE; #else /* if we need a specified source address then go straight to it */ if (ncsock->local_host.iaddrs[0].s_addr) need_udphelper = FALSE; #endif if (!need_udphelper) { /* simulates a udphelper_sockets_open() call */ sockbuf = calloc(2, sizeof(int)); sockbuf[0] = 1; sockbuf[1] = sock = netcat_socket_new(PF_INET, SOCK_DGRAM); } #ifndef USE_PKTINFO else sock = udphelper_sockets_open(&sockbuf, ncsock->local_port.netnum); #endif if (sock < 0) goto err; /* we know that udphelper_sockets_open() returns the highest socket, and if we didn't call it we have just one socket */ sock_max = sock + 1; if (!need_udphelper) { /* prepare myaddr for the bind() call */ myaddr.sin_family = AF_INET; myaddr.sin_port = ncsock->local_port.netnum; memcpy(&myaddr.sin_addr, &ncsock->local_host.iaddrs[0], sizeof(myaddr.sin_addr)); /* bind() MUST be called in this function, since it's the final call for this type of socket. FIXME: I heard that UDP port 0 is illegal. true? */ ret = bind(sock, (struct sockaddr *)&myaddr, sizeof(myaddr)); if (ret < 0) goto err; } #ifdef USE_PKTINFO /* set the right flag in order to obtain the ancillary data */ ret = setsockopt(sock, SOL_IP, IP_PKTINFO, &sockopt, sizeof(sockopt)); if (ret < 0) goto err; #endif /* if the port was set to 0 this means that it is assigned randomly by the OS. Find out which port they assigned to us. */ if (ncsock->local_port.num == 0) { struct sockaddr_in get_myaddr; unsigned int get_myaddr_len = sizeof(get_myaddr); ret = getsockname(sock, (struct sockaddr *)&get_myaddr, &get_myaddr_len); if (ret < 0) goto err; netcat_getport(&ncsock->local_port, NULL, ntohs(get_myaddr.sin_port)); assert(ncsock->local_port.num != 0); } if (!need_udphelper) ncprint(NCPRINT_VERB2, _("Listening on %s"), netcat_strid(&ncsock->local_host, &ncsock->local_port)); else ncprint(NCPRINT_VERB2, _("Listening on %s (using %d sockets)"), netcat_strid(&ncsock->local_host, &ncsock->local_port), sockbuf[0]); /* since this protocol is connectionless, we need a special handling here. We want to simulate a two-ends connection but in order to do this we need a remote address and a local address (in case we bound to INADDR_ANY). Wait here until a packet is received, and use its source and destination addresses as default endpoints. If we have the zero-I/O option set, we just eat the packet and return when timeout is elapsed (maybe never). */ tt.tv_sec = timeout; tt.tv_usec = 0; while (TRUE) { int socks_loop; fd_set ins; FD_ZERO(&ins); for (socks_loop = 1; socks_loop <= sockbuf[0]; socks_loop++) { debug_v(("Setting sock %d on ins", sockbuf[socks_loop])); FD_SET(sockbuf[socks_loop], &ins); } /* automatically use remaining timeout time if in zero-I/O mode */ ret = select(sock_max, &ins, NULL, NULL, (timeout > 0 ? &tt : NULL)); if (ret == 0) break; /* loop all the open sockets to find the active one */ for (socks_loop = 1; socks_loop <= sockbuf[0]; socks_loop++) { int recv_ret, write_ret; struct msghdr my_hdr; #ifdef __MVS__ /* zosunix01 26.07.2011 */ unsigned char buf[32768]; #else unsigned char buf[1024]; #endif struct iovec my_hdr_vec; struct sockaddr_in rem_addr; struct sockaddr_in local_addr; #ifdef USE_PKTINFO unsigned char anc_buf[512]; #endif sock = sockbuf[socks_loop]; if (!FD_ISSET(sock, &ins)) continue; /* I've looked for this code for a lot of hours, and finally found the RFC 2292 which provides a socket API for fetching the destination interface of the incoming packet. */ memset(&my_hdr, 0, sizeof(my_hdr)); memset(&rem_addr, 0, sizeof(rem_addr)); memset(&local_addr, 0, sizeof(local_addr)); my_hdr.msg_name = (void *)&rem_addr; my_hdr.msg_namelen = sizeof(rem_addr); /* initialize the vector struct and then the vectory member of the header */ my_hdr_vec.iov_base = buf; my_hdr_vec.iov_len = sizeof(buf); my_hdr.msg_iov = &my_hdr_vec; my_hdr.msg_iovlen = 1; #ifdef USE_PKTINFO /* now the core part for the IP_PKTINFO support: the ancillary data */ my_hdr.msg_control = anc_buf; my_hdr.msg_controllen = sizeof(anc_buf); #endif /* now check the remote address. If we are simulating a routing then use the MSG_PEEK flag, which leaves the received packet untouched */ recv_ret = recvmsg(sock, &my_hdr, (opt_zero ? 0 : MSG_PEEK)); debug_v(("received packet from %s:%d%s", netcat_inet_ntop(&rem_addr.sin_addr), ntohs(rem_addr.sin_port), (opt_zero ? "" : ", using as default dest"))); #ifdef USE_PKTINFO ret = udphelper_ancillary_read(&my_hdr, &local_addr); local_addr.sin_port = myaddr.sin_port; local_addr.sin_family = myaddr.sin_family; #else ret = sizeof(local_addr); ret = getsockname(sock, (struct sockaddr *)&local_addr, &ret); #endif if (ret == 0) { char tmpbuf[127]; strncpy(tmpbuf, netcat_inet_ntop(&rem_addr.sin_addr), sizeof(tmpbuf)); ncprint(NCPRINT_VERB1, _("Received packet from %s:%d -> %s:%d (local)"), tmpbuf, ntohs(rem_addr.sin_port), netcat_inet_ntop(&local_addr.sin_addr), ntohs(local_addr.sin_port)); } else ncprint(NCPRINT_VERB1, _("Received packet from %s:%d"), netcat_inet_ntop(&rem_addr.sin_addr), ntohs(rem_addr.sin_port)); if (opt_zero) { /* output the packet right here right now */ write_ret = write(STDOUT_FILENO, buf, recv_ret); bytes_recv += write_ret; debug_dv(("write_u(stdout) = %d", write_ret)); if (write_ret < 0) { perror("write_u(stdout)"); exit(EXIT_FAILURE); } /* FIXME: unhandled exception */ assert(write_ret == recv_ret); /* if the hexdump option is set, hexdump the received data */ if (opt_hexdump) { #ifndef USE_OLD_HEXDUMP fprintf(output_fp, "Received %d bytes from %s:%d\n", recv_ret, netcat_inet_ntop(&rem_addr.sin_addr), ntohs(rem_addr.sin_port)); #endif netcat_fhexdump(output_fp, '<', buf, write_ret); } } else { #ifdef USE_PKTINFO nc_sock_t dup_socket; memset(&dup_socket, 0, sizeof(dup_socket)); dup_socket.domain = ncsock->domain; dup_socket.proto = ncsock->proto; memcpy(&dup_socket.local_host.iaddrs[0], &local_addr.sin_addr, sizeof(local_addr)); memcpy(&dup_socket.host.iaddrs[0], &rem_addr.sin_addr, sizeof(local_addr)); dup_socket.local_port.netnum = local_addr.sin_port; dup_socket.local_port.num = ntohs(local_addr.sin_port); dup_socket.port.netnum = rem_addr.sin_port; dup_socket.port.num = ntohs(rem_addr.sin_port); /* copy the received data in the socket's queue */ ncsock->recvq.len = recv_ret; ncsock->recvq.head = ncsock->recvq.pos = malloc(recv_ret); memcpy(ncsock->recvq.head, my_hdr_vec.iov_base, recv_ret); /* FIXME: this ONLY saves the first 1024 bytes! and the others? */ #else ret = connect(sock, (struct sockaddr *)&rem_addr, sizeof(rem_addr)); if (ret < 0) goto err; /* remove this socket from the array in order not to get it closed */ sockbuf[socks_loop] = -1; #endif udphelper_sockets_close(sockbuf); #ifdef USE_PKTINFO /* this is all we want from this function */ debug_dv(("calling the udp_connect() function...")); return core_udp_connect(&dup_socket); #else return sock; #endif } } /* end of foreach (sock, sockbuf) */ } /* end of packet receiving loop */ /* no packets until timeout, set errno and proceed to general error handling */ errno = ETIMEDOUT; err: udphelper_sockets_close(sockbuf); return -1; } /* end of core_udp_listen() */
int netcat_socket_new_connect(int domain, int type, const struct in_addr *addr, in_port_t port, const struct in_addr *local_addr, in_port_t local_port) { int sock, ret, my_family = AF_UNSPEC; struct sockaddr_in rem_addr; assert(addr); debug_dv(("netcat_socket_new_connect(addr=%p, port=%hu, local_addr=%p, local_" "port=%hu)", (void *)addr, ntohs(port), (void *)local_addr, ntohs(local_port))); /* selects the currently supported domains */ if (domain == PF_INET) my_family = AF_INET; else return -1; /* assumes as the socket(2) call failed */ memset(&rem_addr, 0, sizeof(rem_addr)); rem_addr.sin_family = my_family; rem_addr.sin_port = port; memcpy(&rem_addr.sin_addr, addr, sizeof(rem_addr.sin_addr)); /* create the socket and fix the options */ sock = netcat_socket_new(domain, type); if (sock < 0) return sock; /* just forward the error code */ /* only if needed, bind it to a local address */ if (local_addr || local_port) { struct sockaddr_in my_addr; memset(&my_addr, 0, sizeof(my_addr)); my_addr.sin_family = my_family; my_addr.sin_port = local_port; /* local_addr may not be specified because the user may want to only enforce the local source port */ if (local_addr) memcpy(&my_addr.sin_addr, local_addr, sizeof(my_addr.sin_addr)); ret = bind(sock, (struct sockaddr *)&my_addr, sizeof(my_addr)); if (ret < 0) { ret = -3; goto err; } } /* add the non-blocking flag to this socket */ if ((ret = fcntl(sock, F_GETFL, 0)) >= 0) ret = fcntl(sock, F_SETFL, ret | O_NONBLOCK); if (ret < 0) { ret = -4; goto err; } /* now launch the real connection. Since we are in non-blocking mode, this call will return -1 in MOST cases (on some systems, a connect() to a local address may immediately return successfully) */ ret = connect(sock, (struct sockaddr *)&rem_addr, sizeof(rem_addr)); if ((ret < 0) && (errno != EINPROGRESS)) { ret = -5; goto err; } /* everything went fine, return the (connected or connecting) socket */ return sock; err: /* the if () statement is unuseful, but I need to for declaring vars */ if (ret < 0) { int tmpret, saved_errno = errno; /* the close() calls MUST NOT fail */ tmpret = close(sock); assert(tmpret >= 0); /* restore the original errno */ errno = saved_errno; } return ret; }