static errno_t ppfilter_connect (pp_filter_cookie_t cookie, socket_t so, const struct sockaddr *remote, int connectin) { pp_msg_iprange_t match; pg_table_id_t tableid; filt_start(); struct sockaddr_in6 local; if (0 != sock_getsockname(so, (struct sockaddr*)&local, sizeof(local))) bzero(&local, sizeof(local)); int protocol = 0; (void)sock_gettype(so, NULL, NULL, &protocol); int block = match_address(remote, (const struct sockaddr*)&local, protocol, &match, tableid); mach_timespec_t now; clock_get_calendar_nanotime(&now.tv_sec, (u_int32_t*)&now.tv_nsec); u_int32_t lastConnect = sLastConnect; if (now.tv_sec >= (lastConnect+1)) { (void)ExchangeAtomic(now.tv_sec, &sLastConnect); (void)ExchangeAtomic(0, &pp_stats.pps_conns_per_sec); (void)ExchangeAtomic(0, &pp_stats.pps_blcks_per_sec); } // For now we always log even if a log client is not connected, that way // we keep as many records as possible so when a log client connects // it can save them. #ifdef notyet if (pp_logclients && (block || pp_logallowed)) { #endif const struct sockaddr *to, *from; if (!connectin) { to = remote; from = (const struct sockaddr*)&local; } else { to = (const struct sockaddr*)&local; from = remote; } ppfilter_log(block, from, to, remote, protocol, &match, tableid, cookie, &now); #ifdef notyet } #endif if (0 == block) { connectin ? pp_stat_increment(in_allowed) : pp_stat_increment(out_allowed); } else { connectin ? pp_stat_increment(in_blocked) : pp_stat_increment(out_blocked); block = ECONNREFUSED; pp_stat_increment(blcks_per_sec); } pp_stat_increment(conns_per_sec); filt_end(); return (block); }
static int ftp_init_transfer(void) { struct sockaddr_in sa; unsigned char *a, *p; unsigned char pac[6]; if(!ftp_connected()) goto err0; if (!(ftp->data = sock_create())) { goto err0; } sock_copy(ftp->data, ftp->ctrl); if(ftp_is_passive()) { if(ftp_pasv(pac) != 0) { goto err1; } sock_getsockname(ftp->ctrl, &sa); memcpy(&sa.sin_addr, pac, (size_t)4); memcpy(&sa.sin_port, pac+4, (size_t)2); if(sock_connect_addr(ftp->data, &sa) == -1) goto err1; } else { sock_listen(ftp->data); a = (unsigned char *)&ftp->data->local_addr.sin_addr; p = (unsigned char *)&ftp->data->local_addr.sin_port; ftp_set_tmp_verbosity(vbError); ftp_cmd("PORT %d,%d,%d,%d,%d,%d", a[0], a[1], a[2], a[3], p[0], p[1]); if(ftp->code != ctComplete) goto err1; } sock_throughput(ftp->data); return 0; err1: sock_destroy(ftp->data); err0: return -1; }
bool sock_listen(Socket* sockp, int family) { if (!sockp || sockp->handle != -1) return false; sockp->handle = socket(family, SOCK_STREAM, IPPROTO_TCP); if (sockp->handle == -1) return false; socklen_t len = sizeof(struct sockaddr_storage); /* let system pick port TODO */ memset(&sockp->local_addr, 0, len); sockp->local_addr.ss_family = family; if (bind(sockp->handle, (struct sockaddr *)&sockp->local_addr, len) == -1) { perror("bind()"); close(sockp->handle); sockp->handle = -1; return false; } /* wait for an incoming connection */ if (listen(sockp->handle, 1) == -1) { perror("listen()"); close(sockp->handle); sockp->handle = -1; return false; } if (sock_getsockname(sockp, &sockp->local_addr) == -1) { close(sockp->handle); sockp->handle = -1; return false; } return true; }
bool sock_connect_addr(Socket *sockp, const struct sockaddr* sa, socklen_t salen) { if (!sockp || sockp->handle != -1) return false; sockp->handle = socket(sa->sa_family, SOCK_STREAM, IPPROTO_TCP); if (sockp->handle == -1) return false; /* connect to the socket */ if (connect(sockp->handle, sa, salen) == -1) { perror("connect()"); close(sockp->handle); sockp->handle = -1; return false; } if (sock_getsockname(sockp, &sockp->local_addr) == -1) { perror("getsockname()"); close(sockp->handle); sockp->handle = -1; return false; } memcpy(&sockp->remote_addr, sa, salen); if (!create_streams(sockp, "r", "w")) { close(sockp->handle); sockp->handle = -1; return false; } sockp->connected = true; return true; }
int libcfs_sock_read (cfs_socket_t *sock, void *buffer, int nob, int timeout) { size_t rcvlen; int rc; cfs_duration_t to = cfs_time_seconds(timeout); cfs_time_t then; struct timeval tv; LASSERT(nob > 0); for (;;) { struct iovec iov = { .iov_base = buffer, .iov_len = nob }; struct msghdr msg = { .msg_name = NULL, .msg_namelen = 0, .msg_iov = &iov, .msg_iovlen = 1, .msg_control = NULL, .msg_controllen = 0, .msg_flags = 0, }; cfs_duration_usec(to, &tv); rc = -sock_setsockopt(C2B_SOCK(sock), SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); if (rc != 0) { CERROR("Can't set socket recv timeout " "%ld.%06d: %d\n", (long)tv.tv_sec, (int)tv.tv_usec, rc); return rc; } then = cfs_time_current(); rc = -sock_receive(C2B_SOCK(sock), &msg, 0, &rcvlen); to -= cfs_time_current() - then; if (rc != 0 && rc != -EWOULDBLOCK) return rc; if (rcvlen == nob) return 0; if (to <= 0) return -EAGAIN; buffer = ((char *)buffer) + rcvlen; nob -= rcvlen; } return 0; } int libcfs_sock_write (cfs_socket_t *sock, void *buffer, int nob, int timeout) { size_t sndlen; int rc; cfs_duration_t to = cfs_time_seconds(timeout); cfs_time_t then; struct timeval tv; LASSERT(nob > 0); for (;;) { struct iovec iov = { .iov_base = buffer, .iov_len = nob }; struct msghdr msg = { .msg_name = NULL, .msg_namelen = 0, .msg_iov = &iov, .msg_iovlen = 1, .msg_control = NULL, .msg_controllen = 0, .msg_flags = (timeout == 0) ? MSG_DONTWAIT : 0, }; if (timeout != 0) { cfs_duration_usec(to, &tv); rc = -sock_setsockopt(C2B_SOCK(sock), SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); if (rc != 0) { CERROR("Can't set socket send timeout " "%ld.%06d: %d\n", (long)tv.tv_sec, (int)tv.tv_usec, rc); return rc; } } then = cfs_time_current(); rc = -sock_send(C2B_SOCK(sock), &msg, ((timeout == 0) ? MSG_DONTWAIT : 0), &sndlen); to -= cfs_time_current() - then; if (rc != 0 && rc != -EWOULDBLOCK) return rc; if (sndlen == nob) return 0; if (to <= 0) return -EAGAIN; buffer = ((char *)buffer) + sndlen; nob -= sndlen; } return 0; } int libcfs_sock_getaddr (cfs_socket_t *sock, int remote, __u32 *ip, int *port) { struct sockaddr_in sin; int rc; if (remote != 0) /* Get remote address */ rc = -sock_getpeername(C2B_SOCK(sock), (struct sockaddr *)&sin, sizeof(sin)); else /* Get local address */ rc = -sock_getsockname(C2B_SOCK(sock), (struct sockaddr *)&sin, sizeof(sin)); if (rc != 0) { CERROR ("Error %d getting sock %s IP/port\n", rc, remote ? "peer" : "local"); return rc; } if (ip != NULL) *ip = ntohl (sin.sin_addr.s_addr); if (port != NULL) *port = ntohs (sin.sin_port); return 0; } int libcfs_sock_setbuf (cfs_socket_t *sock, int txbufsize, int rxbufsize) { int option; int rc; if (txbufsize != 0) { option = txbufsize; rc = -sock_setsockopt(C2B_SOCK(sock), SOL_SOCKET, SO_SNDBUF, (char *)&option, sizeof (option)); if (rc != 0) { CERROR ("Can't set send buffer %d: %d\n", option, rc); return (rc); } } if (rxbufsize != 0) { option = rxbufsize; rc = -sock_setsockopt (C2B_SOCK(sock), SOL_SOCKET, SO_RCVBUF, (char *)&option, sizeof (option)); if (rc != 0) { CERROR ("Can't set receive buffer %d: %d\n", option, rc); return (rc); } } return 0; }
/* * System call vectors. Since I (RIB) want to rewrite sockets as streams, * we have this level of indirection. Not a lot of overhead, since more of * the work is done via read/write/select directly. */ asmlinkage int sys_socketcall(int call, unsigned long *args) { int er; switch(call) { case SYS_SOCKET: er=verify_area(VERIFY_READ, args, 3 * sizeof(long)); if(er) return er; return(sock_socket(get_fs_long(args+0), get_fs_long(args+1), get_fs_long(args+2))); case SYS_BIND: er=verify_area(VERIFY_READ, args, 3 * sizeof(long)); if(er) return er; return(sock_bind(get_fs_long(args+0), (struct sockaddr *)get_fs_long(args+1), get_fs_long(args+2))); case SYS_CONNECT: er=verify_area(VERIFY_READ, args, 3 * sizeof(long)); if(er) return er; return(sock_connect(get_fs_long(args+0), (struct sockaddr *)get_fs_long(args+1), get_fs_long(args+2))); case SYS_LISTEN: er=verify_area(VERIFY_READ, args, 2 * sizeof(long)); if(er) return er; return(sock_listen(get_fs_long(args+0), get_fs_long(args+1))); case SYS_ACCEPT: er=verify_area(VERIFY_READ, args, 3 * sizeof(long)); if(er) return er; return(sock_accept(get_fs_long(args+0), (struct sockaddr *)get_fs_long(args+1), (int *)get_fs_long(args+2))); case SYS_GETSOCKNAME: er=verify_area(VERIFY_READ, args, 3 * sizeof(long)); if(er) return er; return(sock_getsockname(get_fs_long(args+0), (struct sockaddr *)get_fs_long(args+1), (int *)get_fs_long(args+2))); case SYS_GETPEERNAME: er=verify_area(VERIFY_READ, args, 3 * sizeof(long)); if(er) return er; return(sock_getpeername(get_fs_long(args+0), (struct sockaddr *)get_fs_long(args+1), (int *)get_fs_long(args+2))); case SYS_SOCKETPAIR: er=verify_area(VERIFY_READ, args, 4 * sizeof(long)); if(er) return er; return(sock_socketpair(get_fs_long(args+0), get_fs_long(args+1), get_fs_long(args+2), (unsigned long *)get_fs_long(args+3))); case SYS_SEND: er=verify_area(VERIFY_READ, args, 4 * sizeof(unsigned long)); if(er) return er; return(sock_send(get_fs_long(args+0), (void *)get_fs_long(args+1), get_fs_long(args+2), get_fs_long(args+3))); case SYS_SENDTO: er=verify_area(VERIFY_READ, args, 6 * sizeof(unsigned long)); if(er) return er; return(sock_sendto(get_fs_long(args+0), (void *)get_fs_long(args+1), get_fs_long(args+2), get_fs_long(args+3), (struct sockaddr *)get_fs_long(args+4), get_fs_long(args+5))); case SYS_RECV: er=verify_area(VERIFY_READ, args, 4 * sizeof(unsigned long)); if(er) return er; return(sock_recv(get_fs_long(args+0), (void *)get_fs_long(args+1), get_fs_long(args+2), get_fs_long(args+3))); case SYS_RECVFROM: er=verify_area(VERIFY_READ, args, 6 * sizeof(unsigned long)); if(er) return er; return(sock_recvfrom(get_fs_long(args+0), (void *)get_fs_long(args+1), get_fs_long(args+2), get_fs_long(args+3), (struct sockaddr *)get_fs_long(args+4), (int *)get_fs_long(args+5))); case SYS_SHUTDOWN: er=verify_area(VERIFY_READ, args, 2* sizeof(unsigned long)); if(er) return er; return(sock_shutdown(get_fs_long(args+0), get_fs_long(args+1))); case SYS_SETSOCKOPT: er=verify_area(VERIFY_READ, args, 5*sizeof(unsigned long)); if(er) return er; return(sock_setsockopt(get_fs_long(args+0), get_fs_long(args+1), get_fs_long(args+2), (char *)get_fs_long(args+3), get_fs_long(args+4))); case SYS_GETSOCKOPT: er=verify_area(VERIFY_READ, args, 5*sizeof(unsigned long)); if(er) return er; return(sock_getsockopt(get_fs_long(args+0), get_fs_long(args+1), get_fs_long(args+2), (char *)get_fs_long(args+3), (int *)get_fs_long(args+4))); default: return(-EINVAL); } }
errno_t IOWebFilterClass::tl_connect_out_func(void *cookie, socket_t so, const struct sockaddr *to) { SocketTracker *tracker = (SocketTracker*)cookie; if(tracker==NULL || tracker->magic!=kSocketTrackerAttach) return 0; if(tracker->lock==NULL) { tracker->magic=kSocketTrackerInvalid; LOG(LOG_DEBUG, "I am in, %s, magic=%ld", tracker->proc_name, tracker->magic); return 0; } struct sockaddr_in *sock_addr = (struct sockaddr_in*)to; //just handle the ipv4 address if(sock_addr!=NULL) { if(sock_addr->sin_family==AF_INET6) tracker->magic=kSocketTrackerInvalid; LOG(LOG_DEBUG, "I am in, %s, magic=%ld", tracker->proc_name, tracker->magic); return 0; } if(tracker->lock) IOLockLock(tracker->lock); tracker->magic=kSocketTrackerConnect; //update status //record source information struct sockaddr sockname; bzero(&sockname, sizeof(sockname)); sock_getsockname(so, &sockname, sizeof(sockname)); if(sockname.sa_family==AF_INET6) { tracker->magic=kSocketTrackerInvalid; if(tracker->lock) IOLockUnlock(tracker->lock); return 0; } tracker->source.family = ((struct sockaddr_in*)&sockname)->sin_family; tracker->source.port = ((struct sockaddr_in*)&sockname)->sin_port; bzero(tracker->source.ip, sizeof(tracker->source.ip)); snprintf(tracker->source.ip, sizeof(tracker->source.ip), "%u.%u.%u.%u", IPV4_ADDR(sock_addr->sin_addr.s_addr)); //record destination information tracker->destination.family=sock_addr->sin_family; tracker->destination.port = sock_addr->sin_port; bzero(tracker->destination.ip, sizeof(tracker->destination.ip)); snprintf(tracker->destination.ip, sizeof(tracker->destination.ip), "%u.%u.%u.%u", IPV4_ADDR(sock_addr->sin_addr.s_addr)); if(strncmp(tracker->destination.ip, "127.0.0.1", sizeof("127.0.0.1"))==0 || (tracker->destination.port!=80 && tracker->destination.port!=8080)) { tracker->magic=kSocketTrackerInvalid; if(tracker->lock) IOLockUnlock(tracker->lock); return 0; } if(tracker->lock) IOLockUnlock(tracker->lock); return 0; }