bool Connection::sendOutgoingMessage(std::unique_ptr<MessageEncoder> encoder) { COMPILE_ASSERT(sizeof(MessageInfo) + attachmentMaxAmount * sizeof(size_t) <= messageMaxSize, AttachmentsFitToMessageInline); Vector<Attachment> attachments = encoder->releaseAttachments(); if (attachments.size() > (attachmentMaxAmount - 1)) { ASSERT_NOT_REACHED(); return false; } MessageInfo messageInfo(encoder->bufferSize(), attachments.size()); size_t messageSizeWithBodyInline = sizeof(messageInfo) + (attachments.size() * sizeof(AttachmentInfo)) + encoder->bufferSize(); if (messageSizeWithBodyInline > messageMaxSize && encoder->bufferSize()) { RefPtr<WebKit::SharedMemory> oolMessageBody = WebKit::SharedMemory::allocate(encoder->bufferSize()); if (!oolMessageBody) return false; WebKit::SharedMemory::Handle handle; if (!oolMessageBody->createHandle(handle, WebKit::SharedMemory::Protection::ReadOnly)) return false; messageInfo.setMessageBodyIsOutOfLine(); memcpy(oolMessageBody->data(), encoder->buffer(), encoder->bufferSize()); attachments.append(handle.releaseAttachment()); } struct msghdr message; memset(&message, 0, sizeof(message)); struct iovec iov[3]; memset(&iov, 0, sizeof(iov)); message.msg_iov = iov; int iovLength = 1; iov[0].iov_base = reinterpret_cast<void*>(&messageInfo); iov[0].iov_len = sizeof(messageInfo); std::unique_ptr<AttachmentInfo[]> attachmentInfo; MallocPtr<char> attachmentFDBuffer; if (!attachments.isEmpty()) { int* fdPtr = 0; size_t attachmentFDBufferLength = std::count_if(attachments.begin(), attachments.end(), [](const Attachment& attachment) { return attachment.fileDescriptor() != -1; }); if (attachmentFDBufferLength) { attachmentFDBuffer = MallocPtr<char>::malloc(sizeof(char) * CMSG_SPACE(sizeof(int) * attachmentFDBufferLength)); message.msg_control = attachmentFDBuffer.get(); message.msg_controllen = CMSG_SPACE(sizeof(int) * attachmentFDBufferLength); memset(message.msg_control, 0, message.msg_controllen); struct cmsghdr* cmsg = CMSG_FIRSTHDR(&message); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; cmsg->cmsg_len = CMSG_LEN(sizeof(int) * attachmentFDBufferLength); fdPtr = reinterpret_cast<int*>(CMSG_DATA(cmsg)); } attachmentInfo = std::make_unique<AttachmentInfo[]>(attachments.size()); int fdIndex = 0; for (size_t i = 0; i < attachments.size(); ++i) { attachmentInfo[i].setType(attachments[i].type()); switch (attachments[i].type()) { case Attachment::MappedMemoryType: attachmentInfo[i].setSize(attachments[i].size()); // Fall trhough, set file descriptor or null. case Attachment::SocketType: if (attachments[i].fileDescriptor() != -1) { ASSERT(fdPtr); fdPtr[fdIndex++] = attachments[i].fileDescriptor(); } else attachmentInfo[i].setNull(); break; case Attachment::Uninitialized: default: break; } } iov[iovLength].iov_base = attachmentInfo.get(); iov[iovLength].iov_len = sizeof(AttachmentInfo) * attachments.size(); ++iovLength; } if (!messageInfo.isMessageBodyIsOutOfLine() && encoder->bufferSize()) { iov[iovLength].iov_base = reinterpret_cast<void*>(encoder->buffer()); iov[iovLength].iov_len = encoder->bufferSize(); ++iovLength; } message.msg_iovlen = iovLength; while (sendmsg(m_socketDescriptor, &message, 0) == -1) { if (errno == EINTR) continue; if (errno == EAGAIN || errno == EWOULDBLOCK) { struct pollfd pollfd; pollfd.fd = m_socketDescriptor; pollfd.events = POLLOUT; pollfd.revents = 0; poll(&pollfd, 1, -1); continue; } if (m_isConnected) WTFLogAlways("Error sending IPC message: %s", strerror(errno)); return false; } return true; }
//RY: start here void udp_xmit6 (struct buffer6 *buf, struct tunnel6 *t) { struct cmsghdr *cmsg; char cbuf[CMSG_SPACE(sizeof (unsigned int))]; unsigned int *refp; struct msghdr msgh; int err; struct iovec iov; //RY: start, for testing struct sockaddr_in6 clientaddr; struct iovec iov1[1]; char a[10]; //RY: end /* * OKAY, now send a packet with the right SAref values. */ memset(&msgh, 0, sizeof(struct msghdr)); msgh.msg_control = cbuf; msgh.msg_controllen = 0; //TODO: need to take decision on IPSEC if(gconfig.ipsecsaref && t->refhim != IPSEC_SAREF_NULL) { msgh.msg_controllen = sizeof(cbuf); cmsg = CMSG_FIRSTHDR(&msgh); cmsg->cmsg_level = SOL_IP; //RY: start //cmsg->cmsg_type = IP_IPSEC_REFINFO; cmsg->cmsg_type = IPV6_DSTOPTS; //RY: updated for IPV6 com. //RY: end cmsg->cmsg_len = CMSG_LEN(sizeof(unsigned int)); if(gconfig.debug_network) { l2tp_log(LOG_DEBUG,"sending with saref=%d\n", t->refhim); } refp = (unsigned int *)CMSG_DATA(cmsg); *refp = t->refhim; msgh.msg_controllen = cmsg->cmsg_len; } iov.iov_base = buf->start; iov.iov_len = buf->len; /* return packet from whence it came */ //RY: start inet_pton(AF_INET6, "2003::1", &buf->peer.sin6_addr); buf->peer.sin6_family = AF_INET6; buf->peer.sin6_port = htons(1701); //RY: end msgh.msg_name = &buf->peer; msgh.msg_namelen = sizeof(buf->peer); msgh.msg_iov = &iov; msgh.msg_iovlen = 1; msgh.msg_flags = 0; #if 0 //RY: start inet_pton(AF_INET6, "2005::1", &buf->peer.sin6_addr); printf("dest addr:%s\n", IPADDY6(buf->peer.sin6_addr)); buf->peer.sin6_family = AF_INET6; buf->peer.sin6_port = htons(23156); msgh.msg_name = &buf->peer; iov.iov_base = a; iov.iov_len = sizeof(a); msgh.msg_iov->iov_base = &iov; msgh.msg_iovlen = 1; msgh.msg_control = NULL; msgh.msg_controllen = 0; msgh.msg_flags = 0; //#ifdef RY: // memset(&clientaddr, 0, sizeof(clientaddr)); // inet_pton(AF_INET6,"2005::1", &clientaddr.sin6_addr); // clientaddr.sin6_port = htons(1701); // clientaddr.sin6_family = AF_INET6; // memset(a, 'a', sizeof(a)); // for(;;) // sendto(server_socket6, a, sizeof(a), 0, // &clientaddr, sizeof(clientaddr)); // for(;;) #endif //for(;;) if((err = sendmsg(server_socket6, &msgh, 0)) < 0) { //RY: start printf("udp_xmit6 failed with err=%d:%s\n",err,strerror(errno)); //RY: end l2tp_log(LOG_ERR, "udp_xmit6 failed with err=%d:%s\n", err,strerror(errno)); }//RY: start else { printf("sent:bytes = %d\n", err); //sleep(1) } //RY: end }
ssize_t recvfrom_flags(int fd, void *ptr, size_t nbytes, int *flagsp, struct sockaddr *sa, socklen_t *salenptr, struct my_in_pktinfo *pktp, u_char *ttl) { struct msghdr msg; struct iovec iov[1]; ssize_t n; #ifdef CMSG_FIRSTHDR struct cmsghdr *cmptr; union { struct cmsghdr cm; char control[1024]; } control_un; *ttl = 255; // If kernel fails to provide TTL data then assume the TTL was 255 as it should be msg.msg_control = control_un.control; msg.msg_controllen = sizeof(control_un.control); msg.msg_flags = 0; #else memset(&msg, 0, sizeof(msg)); /* make certain msg_accrightslen = 0 */ #endif /* CMSG_FIRSTHDR */ msg.msg_name = (char *) sa; msg.msg_namelen = *salenptr; iov[0].iov_base = (char *)ptr; iov[0].iov_len = nbytes; msg.msg_iov = iov; msg.msg_iovlen = 1; if ( (n = recvmsg(fd, &msg, *flagsp)) < 0) return(n); *salenptr = msg.msg_namelen; /* pass back results */ if (pktp) { /* 0.0.0.0, i/f = -1 */ /* We set the interface to -1 so that the caller can tell whether we returned a meaningful value or just some default. Previously this code just set the value to 0, but I'm concerned that 0 might be a valid interface value. */ memset(pktp, 0, sizeof(struct my_in_pktinfo)); pktp->ipi_ifindex = -1; } /* end recvfrom_flags1 */ /* include recvfrom_flags2 */ #ifndef CMSG_FIRSTHDR #warning CMSG_FIRSTHDR not defined. Will not be able to determine destination address, received interface, etc. *flagsp = 0; /* pass back results */ return(n); #else *flagsp = msg.msg_flags; /* pass back results */ if (msg.msg_controllen < (socklen_t)sizeof(struct cmsghdr) || (msg.msg_flags & MSG_CTRUNC) || pktp == NULL) return(n); for (cmptr = CMSG_FIRSTHDR(&msg); cmptr != NULL; cmptr = CMSG_NXTHDR(&msg, cmptr)) { #ifdef IP_PKTINFO #if in_pktinfo_definition_is_missing struct in_pktinfo { int ipi_ifindex; struct in_addr ipi_spec_dst; struct in_addr ipi_addr; }; #endif if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO) { struct in_pktinfo *tmp; struct sockaddr_in *sin = (struct sockaddr_in*)&pktp->ipi_addr; tmp = (struct in_pktinfo *) CMSG_DATA(cmptr); sin->sin_family = AF_INET; sin->sin_addr = tmp->ipi_addr; sin->sin_port = 0; pktp->ipi_ifindex = tmp->ipi_ifindex; continue; } #endif #ifdef IP_RECVDSTADDR if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR) { struct sockaddr_in *sin = (struct sockaddr_in*)&pktp->ipi_addr; sin->sin_family = AF_INET; sin->sin_addr = *(struct in_addr*)CMSG_DATA(cmptr); sin->sin_port = 0; continue; } #endif #ifdef IP_RECVIF if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF) { struct sockaddr_dl *sdl = (struct sockaddr_dl *) CMSG_DATA(cmptr); #ifndef HAVE_BROKEN_RECVIF_NAME int nameLen = (sdl->sdl_nlen < IFI_NAME - 1) ? sdl->sdl_nlen : (IFI_NAME - 1); strncpy(pktp->ipi_ifname, sdl->sdl_data, nameLen); #endif pktp->ipi_ifindex = sdl->sdl_index; assert(pktp->ipi_ifname[IFI_NAME - 1] == 0); // null terminated because of memset above continue; } #endif #ifdef IP_RECVTTL if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVTTL) { *ttl = *(u_char*)CMSG_DATA(cmptr); continue; } else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_TTL) { // some implementations seem to send IP_TTL instead of IP_RECVTTL *ttl = *(int*)CMSG_DATA(cmptr); continue; } #endif #if defined(IPV6_PKTINFO) && HAVE_IPV6 if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == IPV6_PKTINFO) { struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&pktp->ipi_addr; struct in6_pktinfo *ip6_info = (struct in6_pktinfo*)CMSG_DATA(cmptr); sin6->sin6_family = AF_INET6; #ifndef NOT_HAVE_SA_LEN sin6->sin6_len = sizeof(*sin6); #endif sin6->sin6_addr = ip6_info->ipi6_addr; sin6->sin6_flowinfo = 0; sin6->sin6_scope_id = 0; sin6->sin6_port = 0; pktp->ipi_ifindex = ip6_info->ipi6_ifindex; continue; } #endif #if defined(IPV6_HOPLIMIT) && HAVE_IPV6 if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == IPV6_HOPLIMIT) { *ttl = *(int*)CMSG_DATA(cmptr); continue; } #endif assert(0); // unknown ancillary data } return(n); #endif /* CMSG_FIRSTHDR */ }
static int32_t qb_ipcs_uc_recv_and_auth(int32_t sock, void *msg, size_t len, struct ipc_auth_ugp *ugp) { int32_t res = 0; struct msghdr msg_recv; struct iovec iov_recv; #ifdef SO_PASSCRED char cmsg_cred[CMSG_SPACE(sizeof(struct ucred))]; int off = 0; int on = 1; #endif msg_recv.msg_iov = &iov_recv; msg_recv.msg_iovlen = 1; msg_recv.msg_name = 0; msg_recv.msg_namelen = 0; #ifdef SO_PASSCRED msg_recv.msg_control = (void *)cmsg_cred; msg_recv.msg_controllen = sizeof(cmsg_cred); #endif #ifdef QB_SOLARIS msg_recv.msg_accrights = 0; msg_recv.msg_accrightslen = 0; #else msg_recv.msg_flags = 0; #endif /* QB_SOLARIS */ iov_recv.iov_base = msg; iov_recv.iov_len = len; #ifdef SO_PASSCRED setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)); #endif res = qb_ipc_us_recv_msghdr(sock, &msg_recv, msg, len); if (res < 0) { goto cleanup_and_return; } if (res != len) { res = -EIO; goto cleanup_and_return; } /* * currently support getpeerucred, getpeereid, and SO_PASSCRED credential * retrieval mechanisms for various Platforms */ #ifdef HAVE_GETPEERUCRED /* * Solaris and some BSD systems */ { ucred_t *uc = NULL; if (getpeerucred(sock, &uc) == 0) { res = 0; ugp->uid = ucred_geteuid(uc); ugp->gid = ucred_getegid(uc); ugp->pid = ucred_getpid(uc); ucred_free(uc); } else { res = -errno; } } #elif HAVE_GETPEEREID /* * Usually MacOSX systems */ { /* * TODO get the peer's pid. * c->pid = ?; */ if (getpeereid(sock, &ugp->uid, &ugp->gid) == 0) { res = 0; } else { res = -errno; } } #elif SO_PASSCRED /* * Usually Linux systems */ { struct ucred cred; struct cmsghdr *cmsg; res = -EINVAL; for (cmsg = CMSG_FIRSTHDR(&msg_recv); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg_recv, cmsg)) { if (cmsg->cmsg_type != SCM_CREDENTIALS) continue; memcpy(&cred, CMSG_DATA(cmsg), sizeof(struct ucred)); res = 0; ugp->pid = cred.pid; ugp->uid = cred.uid; ugp->gid = cred.gid; break; } } #else /* no credentials */ ugp->pid = 0; ugp->uid = 0; ugp->gid = 0; res = -ENOTSUP; #endif /* no credentials */ cleanup_and_return: #ifdef SO_PASSCRED setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &off, sizeof(off)); #endif return res; }
static int ping_recv (PING * p) { int dupflag, n; int hops = -1; struct msghdr msg; struct iovec iov; struct icmp6_hdr *icmp6; struct cmsghdr *cmsg; char cmsg_data[1024]; iov.iov_base = p->ping_buffer; iov.iov_len = _PING_BUFLEN (p, USE_IPV6); msg.msg_name = &p->ping_from.ping_sockaddr6; msg.msg_namelen = sizeof (p->ping_from.ping_sockaddr6); msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = cmsg_data; msg.msg_controllen = sizeof (cmsg_data); msg.msg_flags = 0; n = recvmsg (p->ping_fd, &msg, 0); if (n < 0) return -1; for (cmsg = CMSG_FIRSTHDR (&msg); cmsg; cmsg = CMSG_NXTHDR (&msg, cmsg)) { if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_HOPLIMIT) { hops = *(int *) CMSG_DATA (cmsg); break; } } icmp6 = (struct icmp6_hdr *) p->ping_buffer; if (icmp6->icmp6_type == ICMP6_ECHO_REPLY) { /* We got an echo reply. */ if (ntohs (icmp6->icmp6_id) != p->ping_ident) return -1; /* It's not a response to us. */ if (_PING_TST (p, ntohs (icmp6->icmp6_seq))) { /* We already got the reply for this echo request. */ p->ping_num_rept++; dupflag = 1; } else { _PING_SET (p, ntohs (icmp6->icmp6_seq)); p->ping_num_recv++; dupflag = 0; } print_echo (dupflag, hops, p->ping_closure, &p->ping_dest.ping_sockaddr6, &p->ping_from.ping_sockaddr6, icmp6, n); } else { /* We got an error reply. */ if (!my_echo_reply (p, icmp6)) return -1; /* It's not for us. */ print_icmp_error (&p->ping_from.ping_sockaddr6, icmp6, n); } return 0; }
int SP_ProcPduUtils :: recv_fd( int sockfd ) { struct msghdr msg; struct iovec iov[1]; #ifdef HAVE_MSGHDR_MSG_CONTROL union { cmsghdr cm; char control[CMSG_SPACE(sizeof(int))]; } control_un; struct cmsghdr *cmptr; msg.msg_control = control_un.control; msg.msg_controllen = sizeof(control_un.control); #else int newfd; msg.msg_accrights = (caddr_t) &newfd; msg.msg_accrightslen = sizeof(int); #endif msg.msg_name = NULL; msg.msg_namelen = 0; char buf[1]; iov[0].iov_base = buf; iov[0].iov_len = 1; msg.msg_iov = iov; msg.msg_iovlen = 1; for( ; ; ) { errno = 0; if (recvmsg(sockfd, &msg, 0) <= 0) { if( EINTR == errno ) { continue; } else { return -1; } } else { break; } } #ifdef HAVE_MSGHDR_MSG_CONTROL if ((cmptr = CMSG_FIRSTHDR(&msg)) != NULL && cmptr->cmsg_len == CMSG_LEN(sizeof(int))) { if (cmptr->cmsg_level != SOL_SOCKET) { syslog( LOG_WARNING,"control level != SOL_SOCKET"); return -1; } if (cmptr->cmsg_type != SCM_RIGHTS) { syslog( LOG_WARNING,"control type != SCM_RIGHTS"); return -1; } return *((int *) CMSG_DATA(cmptr)); } else return -1; /* descriptor was not passed */ #else /* *INDENT-OFF* */ if (msg.msg_accrightslen == sizeof(int)) return newfd; else return -1; /* descriptor was not passed */ /* *INDENT-ON* */ #endif /* char tmpbuf[CONTROLLEN]; struct cmsghdr *cmptr = (struct cmsghdr *) tmpbuf; struct iovec iov[1]; struct msghdr msg; char buf[1]; iov[0].iov_base = buf; iov[0].iov_len = sizeof (buf); msg.msg_iov = iov; msg.msg_iovlen = 1; msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_control = cmptr; msg.msg_controllen = CONTROLLEN; for( ; ; ) { errno = 0; if (recvmsg(sockfd, &msg, 0) <= 0) { if( EINTR == errno ) { continue; } else { return -1; } } else { break; } } return *(int *) CMSG_DATA (cmptr); */ }
/* There is a lot of hair here because the alignment rules (and * thus placement) of cmsg headers and length are different for * 32-bit apps. -DaveM */ int cmsghdr_from_user_compat_to_kern(struct msghdr *kmsg, struct sock *sk, unsigned char *stackbuf, int stackbuf_size) { struct compat_cmsghdr __user *ucmsg; struct cmsghdr *kcmsg, *kcmsg_base; compat_size_t ucmlen; __kernel_size_t kcmlen, tmp; int err = -EFAULT; kcmlen = 0; kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf; ucmsg = CMSG_COMPAT_FIRSTHDR(kmsg); while (ucmsg != NULL) { if (get_user(ucmlen, &ucmsg->cmsg_len)) return -EFAULT; /* Catch bogons. */ if (!CMSG_COMPAT_OK(ucmlen, ucmsg, kmsg)) return -EINVAL; tmp = ((ucmlen - CMSG_COMPAT_ALIGN(sizeof(*ucmsg))) + CMSG_ALIGN(sizeof(struct cmsghdr))); tmp = CMSG_ALIGN(tmp); kcmlen += tmp; ucmsg = cmsg_compat_nxthdr(kmsg, ucmsg, ucmlen); } if (kcmlen == 0) return -EINVAL; /* The kcmlen holds the 64-bit version of the control length. * It may not be modified as we do not stick it into the kmsg * until we have successfully copied over all of the data * from the user. */ if (kcmlen > stackbuf_size) kcmsg_base = kcmsg = sock_kmalloc(sk, kcmlen, GFP_KERNEL); if (kcmsg == NULL) return -ENOBUFS; /* Now copy them over neatly. */ memset(kcmsg, 0, kcmlen); ucmsg = CMSG_COMPAT_FIRSTHDR(kmsg); while (ucmsg != NULL) { if (__get_user(ucmlen, &ucmsg->cmsg_len)) goto Efault; if (!CMSG_COMPAT_OK(ucmlen, ucmsg, kmsg)) goto Einval; tmp = ((ucmlen - CMSG_COMPAT_ALIGN(sizeof(*ucmsg))) + CMSG_ALIGN(sizeof(struct cmsghdr))); if ((char *)kcmsg_base + kcmlen - (char *)kcmsg < CMSG_ALIGN(tmp)) goto Einval; kcmsg->cmsg_len = tmp; tmp = CMSG_ALIGN(tmp); if (__get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level) || __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type) || copy_from_user(CMSG_DATA(kcmsg), CMSG_COMPAT_DATA(ucmsg), (ucmlen - CMSG_COMPAT_ALIGN(sizeof(*ucmsg))))) goto Efault; /* Advance. */ kcmsg = (struct cmsghdr *)((char *)kcmsg + tmp); ucmsg = cmsg_compat_nxthdr(kmsg, ucmsg, ucmlen); } /* Ok, looks like we made it. Hook it up and return success. */ kmsg->msg_control = kcmsg_base; kmsg->msg_controllen = kcmlen; return 0; Einval: err = -EINVAL; Efault: if (kcmsg_base != (struct cmsghdr *)stackbuf) sock_kfree_s(sk, kcmsg_base, kcmlen); return err; }
static int32_t qb_ipc_auth_creds(struct ipc_auth_data *data) { int32_t res = 0; /* * currently support getpeerucred, getpeereid, and SO_PASSCRED credential * retrieval mechanisms for various Platforms */ #ifdef HAVE_GETPEERUCRED /* * Solaris and some BSD systems */ { ucred_t *uc = NULL; if (getpeerucred(data->sock, &uc) == 0) { res = 0; data->ugp.uid = ucred_geteuid(uc); data->ugp.gid = ucred_getegid(uc); data->ugp.pid = ucred_getpid(uc); ucred_free(uc); } else { res = -errno; } } #elif defined(HAVE_GETPEEREID) /* * Usually MacOSX systems */ { /* * TODO get the peer's pid. * c->pid = ?; */ if (getpeereid(data->sock, &data->ugp.uid, &data->ugp.gid) == 0) { res = 0; } else { res = -errno; } } #elif defined(SO_PASSCRED) /* * Usually Linux systems */ { struct ucred cred; struct cmsghdr *cmsg; res = -EINVAL; for (cmsg = CMSG_FIRSTHDR(&data->msg_recv); cmsg != NULL; cmsg = CMSG_NXTHDR(&data->msg_recv, cmsg)) { if (cmsg->cmsg_type != SCM_CREDENTIALS) continue; memcpy(&cred, CMSG_DATA(cmsg), sizeof(struct ucred)); res = 0; data->ugp.pid = cred.pid; data->ugp.uid = cred.uid; data->ugp.gid = cred.gid; break; } } #else /* no credentials */ data->ugp.pid = 0; data->ugp.uid = 0; data->ugp.gid = 0; res = -ENOTSUP; #endif /* no credentials */ return res; }
static int process_frames(int dev, int sock, int fd, unsigned long flags) { struct cmsghdr *cmsg; struct msghdr msg; struct iovec iv; struct hcidump_hdr *dh; struct btsnoop_pkt *dp; struct frame frm; struct pollfd fds[2]; int nfds = 0; char *buf, *ctrl; int len, hdr_size = HCIDUMP_HDR_SIZE; if (sock < 0) return -1; if (snap_len < SNAP_LEN) snap_len = SNAP_LEN; if (flags & DUMP_BTSNOOP) hdr_size = BTSNOOP_PKT_SIZE; buf = malloc(snap_len + hdr_size); if (!buf) { perror("Can't allocate data buffer"); return -1; } dh = (void *) buf; dp = (void *) buf; frm.data = buf + hdr_size; ctrl = malloc(100); if (!ctrl) { free(buf); perror("Can't allocate control buffer"); return -1; } if (dev == HCI_DEV_NONE) printf("system: "); else printf("device: hci%d ", dev); printf("snap_len: %d filter: 0x%lx\n", snap_len, parser.filter); memset(&msg, 0, sizeof(msg)); if (mode == SERVER) { struct btsnoop_hdr *hdr = (void *) buf; btsnoop_version = 1; btsnoop_type = 1002; memcpy(hdr->id, btsnoop_id, sizeof(btsnoop_id)); hdr->version = htonl(btsnoop_version); hdr->type = htonl(btsnoop_type); printf("btsnoop version: %d datalink type: %d\n", btsnoop_version, btsnoop_type); len = write(fd, buf, BTSNOOP_HDR_SIZE); if (len < 0) { perror("Can't create dump header"); return -1; } if (len != BTSNOOP_HDR_SIZE) { fprintf(stderr, "Header size mismatch\n"); return -1; } fds[nfds].fd = fd; fds[nfds].events = POLLIN; fds[nfds].revents = 0; nfds++; } fds[nfds].fd = sock; fds[nfds].events = POLLIN; fds[nfds].revents = 0; nfds++; while (1) { int i, n = poll(fds, nfds, -1); if (n <= 0) continue; for (i = 0; i < nfds; i++) { if (fds[i].revents & (POLLHUP | POLLERR | POLLNVAL)) { if (fds[i].fd == sock) printf("device: disconnected\n"); else printf("client: disconnect\n"); return 0; } } if (mode == SERVER) { len = recv(fd, buf, snap_len, MSG_DONTWAIT); if (len == 0) { printf("client: disconnect\n"); return 0; } if (len < 0 && errno != EAGAIN && errno != EINTR) { perror("Connection read failure"); return -1; } } iv.iov_base = frm.data; iv.iov_len = snap_len; msg.msg_iov = &iv; msg.msg_iovlen = 1; msg.msg_control = ctrl; msg.msg_controllen = 100; len = recvmsg(sock, &msg, MSG_DONTWAIT); if (len < 0) { if (errno == EAGAIN || errno == EINTR) continue; perror("Receive failed"); return -1; } /* Process control message */ frm.data_len = len; frm.dev_id = dev; frm.in = 0; frm.pppdump_fd = parser.pppdump_fd; frm.audio_fd = parser.audio_fd; cmsg = CMSG_FIRSTHDR(&msg); while (cmsg) { int dir; switch (cmsg->cmsg_type) { case HCI_CMSG_DIR: memcpy(&dir, CMSG_DATA(cmsg), sizeof(int)); frm.in = (uint8_t) dir; break; case HCI_CMSG_TSTAMP: memcpy(&frm.ts, CMSG_DATA(cmsg), sizeof(struct timeval)); break; } cmsg = CMSG_NXTHDR(&msg, cmsg); } frm.ptr = frm.data; frm.len = frm.data_len; switch (mode) { case WRITE: case SERVER: /* Save or send dump */ if (flags & DUMP_BTSNOOP) { uint64_t ts; uint8_t pkt_type = ((uint8_t *) frm.data)[0]; dp->size = htonl(frm.data_len); dp->len = dp->size; dp->flags = ntohl(frm.in & 0x01); dp->drops = 0; ts = (frm.ts.tv_sec - 946684800ll) * 1000000ll + frm.ts.tv_usec; dp->ts = hton64(ts + 0x00E03AB44A676000ll); if (pkt_type == HCI_COMMAND_PKT || pkt_type == HCI_EVENT_PKT) dp->flags |= ntohl(0x02); } else { dh->len = htobs(frm.data_len); dh->in = frm.in; dh->ts_sec = htobl(frm.ts.tv_sec); dh->ts_usec = htobl(frm.ts.tv_usec); } if (write_n(fd, buf, frm.data_len + hdr_size) < 0) { perror("Write error"); return -1; } break; default: /* Parse and print */ parse(&frm); break; } } return 0; }
int bind( int sockfd, const struct sockaddr *my_addr, socklen_t addrlen) { #ifdef SO_REUSEPORT // parse environment property (just once) if (reuse_ports.count < 0){ char *env_reuse = getenv("PRIVBIND_REUSE_PORTS"); if (env_reuse == NULL){ reuse_ports.count = 0; }else{ if (parselist(env_reuse, &reuse_ports, 1, 65535) != 0){ reuse_ports.count = -1; return -1; } } } // get bind port int port = -1; if (my_addr->sa_family==AF_INET) port = (int) ntohs(((struct sockaddr_in *) my_addr)->sin_port); else if (my_addr->sa_family==AF_INET6) port = (int) ntohs(((struct sockaddr_in6 *) my_addr)->sin6_port); // check if we should setup SO_REUSEPORT for this port if (port != -1 && is_in_list(&reuse_ports, port)){ int optval = 1; int retval = setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval)); if (retval != 0) return retval; } #endif /* First of all, attempt the bind. We only need the socket if it fails with access denied */ int oret=_bind( sockfd, my_addr, addrlen ); if( oret==0 || errno!=EACCES ) return oret; /* In most cases, we can let the bind go through as is */ if( master_quit || (my_addr->sa_family!=AF_INET && my_addr->sa_family!=AF_INET6) || (my_addr->sa_family==AF_INET && addrlen<sizeof(struct sockaddr_in)) || (my_addr->sa_family==AF_INET6 && addrlen<sizeof(struct sockaddr_in6)) ) { errno=EACCES; return oret; } /* Prepare the ancillary data for passing the actual FD */ struct msghdr msghdr={.msg_name=NULL}; struct cmsghdr *cmsg; char buf[CMSG_SPACE(sizeof(int))]; int *fdptr; msghdr.msg_control=buf; msghdr.msg_controllen=sizeof(buf); cmsg=CMSG_FIRSTHDR(&msghdr); cmsg->cmsg_level=SOL_SOCKET; cmsg->cmsg_type=SCM_RIGHTS; cmsg->cmsg_len=CMSG_LEN(sizeof(int)); /* Initialize the payload */ fdptr=(int *)CMSG_DATA(cmsg); fdptr[0]=sockfd; msghdr.msg_controllen=cmsg->cmsg_len; /* Don't forget the data component */ struct ipc_msg_req request; struct iovec iov; msghdr.msg_iov=&iov; msghdr.msg_iovlen=1; iov.iov_base=&request; iov.iov_len=sizeof(request); request.type=MSG_REQ_BIND; /* Check family of the request, only INET and INET6 should make it here */ if (my_addr->sa_family==AF_INET) request.data.bind4.addr=*(struct sockaddr_in *) my_addr; else if (my_addr->sa_family==AF_INET6) request.data.bind6.addr=*(struct sockaddr_in6 *) my_addr; int retval=oret; if( acquire_lock(1) ) { if( sendmsg( COMM_SOCKET, &msghdr, MSG_NOSIGNAL )>0 ) { /* Request was sent - wait for reply */ struct ipc_msg_reply reply; if( recv( COMM_SOCKET, &reply, sizeof(reply), 0 )>0 ) { retval=reply.data.stat.retval; if( retval<0 ) errno=reply.data.stat.error; } else { /* It would appear that the other process has closed, just return the original retval */ master_cleanup(); } } else { /* An error has occured! */ if( errno==EPIPE || errno==ENOTCONN || errno==EBADF ) { master_cleanup(); } else { perror("privbind communication socket error"); master_cleanup(); } } acquire_lock(0); } /* Make sure we return the original errno, regardless of what caused us to fail */ if( retval!=0 ) errno=EACCES; return retval; }
static int process_frames(bdaddr_t address, unsigned long flags) { struct cmsghdr *cmsg; struct msghdr msg; struct iovec iv; struct hcidump_hdr *dh; struct btsnoop_pkt *dp; struct frame frm; struct pollfd fds[2]; int nfds = 0; char *buf, *ctrl; int len, hdr_size = HCIDUMP_HDR_SIZE; int polltimeout = -1; int sock = -1; int device = -1; if (snap_len < SNAP_LEN) snap_len = SNAP_LEN; if (flags & DUMP_BTSNOOP) hdr_size = BTSNOOP_PKT_SIZE; buf = malloc(snap_len + hdr_size); if (!buf) { perror("Can't allocate data buffer"); return -1; } dh = (void *) buf; dp = (void *) buf; frm.data = buf + hdr_size; ctrl = malloc(100); if (!ctrl) { free(buf); perror("Can't allocate control buffer"); return -1; } printf("snap_len: %d filter: 0x%lx\n", snap_len, parser.filter); memset(&msg, 0, sizeof(msg)); while (1) { nfds = 0; if (sock == -1) { device = hci_for_each_dev(0, find_device_by_address_callback, (long)&address); if (device != -1) { sock = open_socket(device, flags); if (sock != -1) { printf("hci%d Connected\n", device); (void)fflush(stdout); onBtConnect(); } } } if (sock != -1) { fds[nfds].fd = sock; fds[nfds].events = POLLIN; fds[nfds].revents = 0; nfds++; } /* ------------------------------------------------------------- */ /* Remote sme */ /* ------------------------------------------------------------- */ #ifdef IPC_IP // If we are not connected attempt to connect if (!smeConnection) { //printf("Sme Connect :: tcp:localhost:10101\n"); //(void)fflush(stdout); smeConnection = ipc_ip_connect("tcp:localhost:10101", NULL, NULL, NULL, NULL); if (smeConnection) { printf("Sme Connected\n"); (void)fflush(stdout); onIpcConnect(); } } if (smeConnection) { fds[nfds].fd = ipc_getFd(smeConnection); fds[nfds].events = POLLIN; fds[nfds].revents = 0; nfds++; } polltimeout = sock==-1?500:smeConnection?-1:500; #endif /* ------------------------------------------------------------- */ (void)fflush(stdout); int i, n = poll(fds, nfds, polltimeout); (void)fflush(stdout); if (n <= 0) continue; for (i = 0; i < nfds; i++) { if (fds[i].revents & (POLLHUP | POLLERR | POLLNVAL)) { if (fds[i].fd == sock) { printf("device: disconnected\n"); sock = -1; onBtDisconnect(); continue; } #ifdef IPC_IP else if (smeConnection && fds[i].fd == ipc_getFd(smeConnection)) { printf("Sme Disconnected\n"); (void)fflush(stdout); ipc_disconnect(smeConnection); smeConnection = NULL; continue; } #endif else { printf("client: disconnect\n"); } } } for (i = 0; i < nfds; i++) { #ifdef IPC_IP if (smeConnection && fds[i].fd == ipc_getFd(smeConnection) && fds[i].revents & (POLLIN | POLLPRI)) { CsrUint8* smeRxBuffer; CsrUint32 smeRxLength = 0; printf("Sme fd Triggered\n"); (void)fflush(stdout); if (ipc_message_recv(smeConnection, 0, &smeRxBuffer, &smeRxLength)) { if (smeRxLength != 0) { if (!remote_bt_signal_receive(NULL, smeRxBuffer, (CsrUint16)smeRxLength)) { printf("Sme unhandled ipc message\n"); (void)fflush(stdout); } ipc_message_free(smeConnection, smeRxBuffer); } continue; } /* Opps Disconnected */ printf("Sme Disconnected\n"); (void)fflush(stdout); ipc_disconnect(smeConnection); smeConnection = NULL; nfds--; onIpcDisconnect(); continue; } #endif if (sock != -1 && fds[i].fd == sock && fds[i].revents & (POLLIN | POLLPRI)) { iv.iov_base = frm.data; iv.iov_len = snap_len; msg.msg_iov = &iv; msg.msg_iovlen = 1; msg.msg_control = ctrl; msg.msg_controllen = 100; len = recvmsg(sock, &msg, MSG_DONTWAIT); if (len < 0) { if (errno == EAGAIN || errno == EINTR) continue; perror("Receive failed"); return -1; } /* Process control message */ frm.data_len = len; frm.dev_id = device; frm.in = 0; frm.pppdump_fd = parser.pppdump_fd; frm.audio_fd = parser.audio_fd; cmsg = CMSG_FIRSTHDR(&msg); while (cmsg) { switch (cmsg->cmsg_type) { case HCI_CMSG_DIR: frm.in = *((int *) CMSG_DATA(cmsg)); break; case HCI_CMSG_TSTAMP: frm.ts = *((struct timeval *) CMSG_DATA(cmsg)); break; } cmsg = CMSG_NXTHDR(&msg, cmsg); } frm.ptr = frm.data; frm.len = frm.data_len; /* Parse and print */ parse(&frm); } } } return 0; }
/* writes generated buffer to desired destination. For TCP syslog, * we use RFC6587 octet-stuffing (unless octet-counting is selected). * This is not great, but doing full blown RFC5425 (TLS) looks like * it is too much for the logger utility. If octet-counting is * selected, we use that. */ static void write_output(const struct logger_ctl *ctl, const char *const msg) { struct iovec iov[4]; int iovlen = 0; char *octet = NULL; /* 1) octen count */ if (ctl->octet_count) { size_t len = xasprintf(&octet, "%zu ", strlen(ctl->hdr) + strlen(msg)); iovec_add_string(iov, iovlen, octet, len); } /* 2) header */ iovec_add_string(iov, iovlen, ctl->hdr, 0); /* 3) message */ iovec_add_string(iov, iovlen, msg, 0); if (!ctl->noact) { struct msghdr message = { 0 }; struct cmsghdr *cmhp; struct ucred *cred; union { struct cmsghdr cmh; char control[CMSG_SPACE(sizeof(struct ucred))]; } cbuf; /* 4) add extra \n to make sure message is terminated */ if ((ctl->socket_type == TYPE_TCP) && !ctl->octet_count) iovec_add_string(iov, iovlen, "\n", 1); message.msg_iov = iov; message.msg_iovlen = iovlen; /* syslog/journald may follow local socket credentials rather * than in the message PID. If we use --id as root than we can * force kernel to accept another valid PID than the real logger(1) * PID. */ if (ctl->pid && !ctl->server && ctl->pid != getpid() && geteuid() == 0 && kill(ctl->pid, 0) == 0) { message.msg_control = cbuf.control; message.msg_controllen = CMSG_SPACE(sizeof(struct ucred)); cmhp = CMSG_FIRSTHDR(&message); cmhp->cmsg_len = CMSG_LEN(sizeof(struct ucred)); cmhp->cmsg_level = SOL_SOCKET; cmhp->cmsg_type = SCM_CREDENTIALS; cred = (struct ucred *) CMSG_DATA(cmhp); cred->pid = ctl->pid; } if (sendmsg(ctl->fd, &message, 0) < 0) warn(_("send message failed")); } if (ctl->stderr_printout) { /* make sure it's terminated for stderr */ if (iovec_memcmp(iov, iovlen, "\n", 1) != 0) iovec_add_string(iov, iovlen, "\n", 1); ignore_result( writev(STDERR_FILENO, iov, iovlen) ); } free(octet); }
int main(int argc, char *argv[]) { int opt; int can; struct ifreq ifr; struct sockaddr_can addr; struct canfd_frame frame; struct iovec iov; struct msghdr msg; struct cmsghdr *cmsg; struct timeval tv, timeout_config = { 0, 0 }; fd_set rdfs; char ctrlmsg[CMSG_SPACE(sizeof(struct timeval)) + CMSG_SPACE(sizeof(__u32))]; int running = 1; int nbytes, maxdlen; int ret; int seed = 0; int door_id, signal_id, speed_id; SDL_Event event; while ((opt = getopt(argc, argv, "rs:dh?")) != -1) { switch(opt) { case 'r': randomize = 1; break; case 's': seed = atoi(optarg); break; case 'd': debug = 1; break; case 'h': case '?': default: Usage(NULL); break; } } if (optind >= argc) Usage("You must specify at least one can device"); if (seed && randomize) Usage("You can not specify a seed value AND randomize the seed"); // Create a new raw CAN socket can = socket(PF_CAN, SOCK_RAW, CAN_RAW); if(can < 0) Usage("Couldn't create raw socket"); addr.can_family = AF_CAN; memset(&ifr.ifr_name, 0, sizeof(ifr.ifr_name)); strncpy(ifr.ifr_name, argv[optind], strlen(argv[optind])); printf("Using CAN interface %s\n", ifr.ifr_name); if (ioctl(can, SIOCGIFINDEX, &ifr) < 0) { perror("SIOCGIFINDEX"); exit(1); } addr.can_ifindex = ifr.ifr_ifindex; // CAN FD Mode setsockopt(can, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &canfd_on, sizeof(canfd_on)); iov.iov_base = &frame; iov.iov_len = sizeof(frame); msg.msg_name = &addr; msg.msg_namelen = sizeof(addr); msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = &ctrlmsg; msg.msg_controllen = sizeof(ctrlmsg); msg.msg_flags = 0; if (bind(can, (struct sockaddr *)&addr, sizeof(addr)) < 0) { perror("bind"); return 1; } init_car_state(); door_id = DEFAULT_DOOR_ID; signal_id = DEFAULT_SIGNAL_ID; speed_id = DEFAULT_SPEED_ID; if (randomize || seed) { if(randomize) seed = time(NULL); srand(seed); door_id = (rand() % 2046) + 1; signal_id = (rand() % 2046) + 1; speed_id = (rand() % 2046) + 1; door_pos = rand() % 9; signal_pos = rand() % 9; speed_pos = rand() % 8; printf("Seed: %d\n", seed); } SDL_Window *window = NULL; SDL_Surface *screenSurface = NULL; if(SDL_Init ( SDL_INIT_VIDEO ) < 0 ) { printf("SDL Could not initializes\n"); exit(40); } window = SDL_CreateWindow("IC Simulator", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN ); if(window == NULL) { printf("Window could not be shown\n"); } renderer = SDL_CreateRenderer(window, -1, 0); SDL_Surface *image = IMG_Load(get_data("ic.png")); SDL_Surface *needle = IMG_Load(get_data("needle.png")); SDL_Surface *sprites = IMG_Load(get_data("spritesheet.png")); base_texture = SDL_CreateTextureFromSurface(renderer, image); needle_tex = SDL_CreateTextureFromSurface(renderer, needle); sprite_tex = SDL_CreateTextureFromSurface(renderer, sprites); speed_rect.x = 212; speed_rect.y = 175; speed_rect.h = needle->h; speed_rect.w = needle->w; // Draw the IC redraw_ic(); /* For now we will just operate on one CAN interface */ while(running) { while( SDL_PollEvent(&event) != 0 ) { switch(event.type) { case SDL_QUIT: running = 0; break; } } nbytes = recvmsg(can, &msg, 0); if (nbytes < 0) { perror("read"); return 1; } if ((size_t)nbytes == CAN_MTU) maxdlen = CAN_MAX_DLEN; else if ((size_t)nbytes == CANFD_MTU) maxdlen = CANFD_MAX_DLEN; else { fprintf(stderr, "read: incomplete CAN frame\n"); return 1; } for (cmsg = CMSG_FIRSTHDR(&msg); cmsg && (cmsg->cmsg_level == SOL_SOCKET); cmsg = CMSG_NXTHDR(&msg,cmsg)) { if (cmsg->cmsg_type == SO_TIMESTAMP) tv = *(struct timeval *)CMSG_DATA(cmsg); else if (cmsg->cmsg_type == SO_RXQ_OVFL) //dropcnt[i] = *(__u32 *)CMSG_DATA(cmsg); fprintf(stderr, "Dropped packet\n"); } // if(debug) fprint_canframe(stdout, &frame, "\n", 0, maxdlen); if(frame.can_id == door_id) update_door_status(&frame, maxdlen); if(frame.can_id == signal_id) update_signal_status(&frame, maxdlen); if(frame.can_id == speed_id) update_speed_status(&frame, maxdlen); } SDL_DestroyTexture(base_texture); SDL_DestroyTexture(needle_tex); SDL_DestroyTexture(sprite_tex); SDL_FreeSurface(image); SDL_FreeSurface(needle); SDL_FreeSurface(sprites); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); IMG_Quit(); SDL_Quit(); return 0; }
void send_packet(struct interface *ifp, struct stream *s, u_int32_t dst, struct prefix *p, u_int32_t ttl) { static struct sockaddr_in sockdst = { AF_INET }; struct ip *ip; struct icmphdr *icmp; struct msghdr *msg; struct cmsghdr *cmsg; struct iovec iovector; char msgbuf[256]; char buf[256]; struct in_pktinfo *pktinfo; u_long src; int on; if (!(ifp->flags & IFF_UP)) return; if (p) src = ntohl(p->u.prefix4.s_addr); else src = 0; /* Is filled in */ ip = (struct ip *)buf; ip->ip_hl = sizeof(struct ip) >> 2; ip->ip_v = IPVERSION; ip->ip_tos = 0xC0; ip->ip_off = 0L; ip->ip_p = 1; /* IP_ICMP */ ip->ip_ttl = ttl; ip->ip_src.s_addr = src; ip->ip_dst.s_addr = dst; icmp = (struct icmphdr *)(buf + sizeof(struct ip)); /* Merge IP header with icmp packet */ assert(stream_get_endp(s) < (sizeof(buf) - sizeof(struct ip))); stream_get(icmp, s, stream_get_endp(s)); /* icmp->checksum is already calculated */ ip->ip_len = sizeof(struct ip) + stream_get_endp(s); on = 1; if (setsockopt(irdp_sock, IPPROTO_IP, IP_HDRINCL, (char *)&on, sizeof(on)) < 0) zlog_warn("sendto %s", safe_strerror(errno)); if (dst == INADDR_BROADCAST) { on = 1; if (setsockopt(irdp_sock, SOL_SOCKET, SO_BROADCAST, (char *)&on, sizeof(on)) < 0) zlog_warn("sendto %s", safe_strerror(errno)); } if (dst != INADDR_BROADCAST) { on = 0; if (setsockopt(irdp_sock, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&on, sizeof(on)) < 0) zlog_warn("sendto %s", safe_strerror(errno)); } memset(&sockdst, 0, sizeof(sockdst)); sockdst.sin_family = AF_INET; sockdst.sin_addr.s_addr = dst; cmsg = (struct cmsghdr *)(msgbuf + sizeof(struct msghdr)); cmsg->cmsg_len = sizeof(struct cmsghdr) + sizeof(struct in_pktinfo); cmsg->cmsg_level = SOL_IP; cmsg->cmsg_type = IP_PKTINFO; pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsg); pktinfo->ipi_ifindex = ifp->ifindex; pktinfo->ipi_spec_dst.s_addr = src; pktinfo->ipi_addr.s_addr = src; iovector.iov_base = (void *)buf; iovector.iov_len = ip->ip_len; msg = (struct msghdr *)msgbuf; msg->msg_name = &sockdst; msg->msg_namelen = sizeof(sockdst); msg->msg_iov = &iovector; msg->msg_iovlen = 1; msg->msg_control = cmsg; msg->msg_controllen = cmsg->cmsg_len; sockopt_iphdrincl_swab_htosys(ip); if (sendmsg(irdp_sock, msg, 0) < 0) { zlog_warn("sendto %s", safe_strerror(errno)); } /* printf("TX on %s idx %d\n", ifp->name, ifp->ifindex); */ }
/** receives an ipv4 packet using a raw socket. * An ipv4 packet is received in buf, using IP_PKTINFO or IP_RECVDSTADDR. * from and to are filled (only the ip part the ports are 0 since this * function doesn't try to look beyond the IP level). * @param sock - raw socket * @param buf - detination buffer. * @param len - buffer len (should be enough for receiving a packet + * IP header). * @param from - result parameter, the IP address part of it will be filled * with the source address and the port with 0. * @param to - result parameter, the IP address part of it will be filled * with the destination (local) address and the port with 0. * @return packet len or <0 on error: -1 (check errno), * -2 no IP_PKTINFO/IP_RECVDSTADDR found or AF mismatch */ int recvpkt4(int sock, char* buf, int len, union sockaddr_union* from, union sockaddr_union* to) { struct iovec iov[1]; struct msghdr rcv_msg; struct cmsghdr* cmsg; #ifdef IP_PKTINFO struct in_pktinfo* rcv_pktinfo; #endif /* IP_PKTINFO */ int n, ret; char msg_ctrl_buf[1024]; iov[0].iov_base=buf; iov[0].iov_len=len; memset(&rcv_msg, 0, sizeof(struct msghdr)); rcv_msg.msg_name=from; rcv_msg.msg_namelen=sockaddru_len(*from); rcv_msg.msg_control=msg_ctrl_buf; rcv_msg.msg_controllen=sizeof(msg_ctrl_buf); rcv_msg.msg_iov=&iov[0]; rcv_msg.msg_iovlen=1; ret=-2; /* no PKT_INFO or AF mismatch */ retry: n=recvmsg(sock, &rcv_msg, MSG_WAITALL); if (unlikely(n==-1)){ if (errno==EINTR) goto retry; ret=n; goto end; } /* find the pkt info */ for (cmsg=CMSG_FIRSTHDR(&rcv_msg); cmsg; cmsg=CMSG_NXTHDR(&rcv_msg, cmsg)){ #ifdef IP_PKTINFO if (likely((cmsg->cmsg_level==IPPROTO_IP) && (cmsg->cmsg_type==IP_PKTINFO))) { rcv_pktinfo=(struct in_pktinfo*)CMSG_DATA(cmsg); to->sin.sin_family=AF_INET; memcpy(&to->sin.sin_addr, &rcv_pktinfo->ipi_spec_dst.s_addr, sizeof(to->sin.sin_addr)); to->sin.sin_port=0; /* not known */ /* interface no. in ipi_ifindex */ ret=n; /* success */ break; } #elif defined (IP_RECVDSTADDR) if (likely((cmsg->cmsg_level==IPPROTO_IP) && (cmsg->cmsg_type==IP_RECVDSTADDR))) { to->sin.sin_family=AF_INET; memcpy(&to->sin.sin_addr, CMSG_DATA(cmsg), sizeof(to->sin.sin_addr)); to->sin.sin_port=0; /* not known */ ret=n; /* success */ break; } #else #error "no method of getting the destination ip address supported" #endif /* IP_PKTINFO / IP_RECVDSTADDR */ } end: return ret; }
static int receive_message(int sock, void *buf, size_t buflen, int *fdp, int *numfds) { struct msghdr msg; struct iovec iov; size_t ccmsg[CMSG_SPACE(sizeof(int) * MAX_SEND_FDS) / sizeof(size_t)]; struct cmsghdr *cmsg; int res; int i; assert(*numfds <= MAX_SEND_FDS); iov.iov_base = buf; iov.iov_len = buflen; memset(&msg, 0, sizeof(msg)); memset(ccmsg, -1, sizeof(ccmsg)); msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = ccmsg; msg.msg_controllen = sizeof(ccmsg); res = recvmsg(sock, &msg, MSG_WAITALL); if (!res) { /* retry on zero return, see do_recv() in ulockmgr.c */ res = recvmsg(sock, &msg, MSG_WAITALL); if (!res) return 0; } if (res == -1) { perror("ulockmgr_server: recvmsg"); return -1; } if ((size_t) res != buflen) { fprintf(stderr, "ulockmgr_server: short message received\n"); return -1; } cmsg = CMSG_FIRSTHDR(&msg); if (cmsg) { if (!cmsg->cmsg_type == SCM_RIGHTS) { fprintf(stderr, "ulockmgr_server: unknown control message %d\n", cmsg->cmsg_type); return -1; } memcpy(fdp, CMSG_DATA(cmsg), sizeof(int) * *numfds); if (msg.msg_flags & MSG_CTRUNC) { fprintf(stderr, "ulockmgr_server: control message truncated\n"); for (i = 0; i < *numfds; i++) close(fdp[i]); *numfds = 0; } } else { if (msg.msg_flags & MSG_CTRUNC) { fprintf(stderr, "ulockmgr_server: control message truncated(*)\n"); /* There's a bug in the Linux kernel, that if not all file descriptors were allocated, then the cmsg header is not filled in */ cmsg = (struct cmsghdr *) ccmsg; memcpy(fdp, CMSG_DATA(cmsg), sizeof(int) * *numfds); for (i = 0; i < *numfds; i++) close(fdp[i]); } *numfds = 0; } return res; }
static int handle_open(struct weston_launch *wl, struct msghdr *msg, ssize_t len) { int fd = -1, ret = -1; char control[CMSG_SPACE(sizeof(fd))]; struct cmsghdr *cmsg; struct stat s; struct msghdr nmsg; struct iovec iov; struct weston_launcher_open *message; union cmsg_data *data; message = msg->msg_iov->iov_base; if ((size_t)len < sizeof(*message)) goto err0; /* Ensure path is null-terminated */ ((char *) message)[len-1] = '\0'; fd = open(message->path, message->flags); if (fd < 0) { fprintf(stderr, "Error opening device %s: %m\n", message->path); goto err0; } if (fstat(fd, &s) < 0) { close(fd); fd = -1; fprintf(stderr, "Failed to stat %s\n", message->path); goto err0; } if (major(s.st_rdev) != INPUT_MAJOR && major(s.st_rdev) != DRM_MAJOR) { close(fd); fd = -1; fprintf(stderr, "Device %s is not an input or drm device\n", message->path); goto err0; } err0: memset(&nmsg, 0, sizeof nmsg); nmsg.msg_iov = &iov; nmsg.msg_iovlen = 1; if (fd != -1) { nmsg.msg_control = control; nmsg.msg_controllen = sizeof control; cmsg = CMSG_FIRSTHDR(&nmsg); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); data = (union cmsg_data *) CMSG_DATA(cmsg); data->fd = fd; nmsg.msg_controllen = cmsg->cmsg_len; ret = 0; } iov.iov_base = &ret; iov.iov_len = sizeof ret; if (wl->verbose) fprintf(stderr, "weston-launch: opened %s: ret: %d, fd: %d\n", message->path, ret, fd); do { len = sendmsg(wl->sock[0], &nmsg, 0); } while (len < 0 && errno == EINTR); if (len < 0) return -1; if (fd != -1 && major(s.st_rdev) == DRM_MAJOR) wl->drm_fd = fd; if (fd != -1 && major(s.st_rdev) == INPUT_MAJOR && wl->last_input_fd < fd) wl->last_input_fd = fd; return 0; }
int main(int argc, char *argv[]) { int sk1, sk2; sockaddr_storage_t loop1; sockaddr_storage_t loop2; struct iovec iov; struct msghdr inmessage; struct msghdr outmessage; char incmsg[CMSG_SPACE(sizeof(sctp_cmsg_data_t))]; char outcmsg[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))]; struct cmsghdr *cmsg; struct sctp_sndrcvinfo *sinfo; struct iovec out_iov; int error; int pf_class, af_family; uint32_t ppid; uint32_t stream; sctp_assoc_t associd1, associd2; struct sctp_assoc_change *sac; struct sctp_event_subscribe subscribe; char *big_buffer; int offset; struct sctp_send_failed *ssf; socklen_t len; /* Really becomes 2xlen when set. */ int orig_len; struct sctp_status gstatus; /* Rather than fflush() throughout the code, set stdout to * be unbuffered. */ setvbuf(stdout, NULL, _IONBF, 0); /* Set some basic values which depend on the address family. */ #if TEST_V6 pf_class = PF_INET6; af_family = AF_INET6; loop1.v6.sin6_family = AF_INET6; loop1.v6.sin6_addr = in6addr_loopback; loop1.v6.sin6_port = htons(SCTP_TESTPORT_1); loop2.v6.sin6_family = AF_INET6; loop2.v6.sin6_addr = in6addr_loopback; loop2.v6.sin6_port = htons(SCTP_TESTPORT_2); #else pf_class = PF_INET; af_family = AF_INET; loop1.v4.sin_family = AF_INET; loop1.v4.sin_addr.s_addr = SCTP_IP_LOOPBACK; loop1.v4.sin_port = htons(SCTP_TESTPORT_1); loop2.v4.sin_family = AF_INET; loop2.v4.sin_addr.s_addr = SCTP_IP_LOOPBACK; loop2.v4.sin_port = htons(SCTP_TESTPORT_2); #endif /* TEST_V6 */ /* Create the two endpoints which will talk to each other. */ sk1 = test_socket(pf_class, SOCK_SEQPACKET, IPPROTO_SCTP); sk2 = test_socket(pf_class, SOCK_SEQPACKET, IPPROTO_SCTP); len = sizeof(int); error = getsockopt(sk2, SOL_SOCKET, SO_RCVBUF, &orig_len, &len); if (error) tst_brkm(TBROK, NULL, "can't get rcvbuf size: %s", strerror(errno)); /* Set the MAXSEG to something smallish. */ { int val = SMALL_MAXSEG; test_setsockopt(sk1, SCTP_MAXSEG, &val, sizeof(val)); } memset(&subscribe, 0, sizeof(subscribe)); subscribe.sctp_data_io_event = 1; subscribe.sctp_association_event = 1; subscribe.sctp_send_failure_event = 1; test_setsockopt(sk1, SCTP_EVENTS, &subscribe, sizeof(subscribe)); test_setsockopt(sk2, SCTP_EVENTS, &subscribe, sizeof(subscribe)); /* Bind these sockets to the test ports. */ test_bind(sk1, &loop1.sa, sizeof(loop1)); test_bind(sk2, &loop2.sa, sizeof(loop2)); /* * This code sets the associations RWND very small so we can * fill it. It does this by manipulating the rcvbuf as follows: * 1) Reduce the rcvbuf size on the socket * 2) create an association so that we advertize rcvbuf/2 as * our initial rwnd * 3) raise the rcvbuf value so that we don't drop data wile * receiving later data */ len = SMALL_RCVBUF; error = setsockopt(sk2, SOL_SOCKET, SO_RCVBUF, &len, sizeof(len)); if (error) tst_brkm(TBROK, NULL, "setsockopt(SO_RCVBUF): %s", strerror(errno)); /* Mark sk2 as being able to accept new associations. */ test_listen(sk2, 1); /* Send the first message. This will create the association. */ outmessage.msg_name = &loop2; outmessage.msg_namelen = sizeof(loop2); outmessage.msg_iov = &out_iov; outmessage.msg_iovlen = 1; outmessage.msg_control = outcmsg; outmessage.msg_controllen = sizeof(outcmsg); outmessage.msg_flags = 0; cmsg = CMSG_FIRSTHDR(&outmessage); cmsg->cmsg_level = IPPROTO_SCTP; cmsg->cmsg_type = SCTP_SNDRCV; cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo)); outmessage.msg_controllen = cmsg->cmsg_len; sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg); memset(sinfo, 0x00, sizeof(struct sctp_sndrcvinfo)); ppid = rand(); /* Choose an arbitrary value. */ stream = 1; sinfo->sinfo_ppid = ppid; sinfo->sinfo_stream = stream; outmessage.msg_iov->iov_base = message; outmessage.msg_iov->iov_len = strlen(message) + 1; test_sendmsg(sk1, &outmessage, 0, strlen(message) + 1); /* Initialize inmessage for all receives. */ big_buffer = test_malloc(REALLY_BIG); memset(&inmessage, 0, sizeof(inmessage)); iov.iov_base = big_buffer; iov.iov_len = REALLY_BIG; inmessage.msg_iov = &iov; inmessage.msg_iovlen = 1; inmessage.msg_control = incmsg; /* Get the communication up message on sk2. */ inmessage.msg_controllen = sizeof(incmsg); error = test_recvmsg(sk2, &inmessage, MSG_WAITALL); test_check_msg_notification(&inmessage, error, sizeof(struct sctp_assoc_change), SCTP_ASSOC_CHANGE, SCTP_COMM_UP); sac = (struct sctp_assoc_change *)iov.iov_base; associd2 = sac->sac_assoc_id; /* Get the communication up message on sk1. */ inmessage.msg_controllen = sizeof(incmsg); error = test_recvmsg(sk1, &inmessage, MSG_WAITALL); test_check_msg_notification(&inmessage, error, sizeof(struct sctp_assoc_change), SCTP_ASSOC_CHANGE, SCTP_COMM_UP); sac = (struct sctp_assoc_change *)iov.iov_base; associd1 = sac->sac_assoc_id; /* restore the rcvbuffer size for the receiving socket */ error = setsockopt(sk2, SOL_SOCKET, SO_RCVBUF, &orig_len, sizeof(orig_len)); if (error) tst_brkm(TBROK, NULL, "setsockopt(SO_RCVBUF): %s", strerror(errno)); /* Get the first data message which was sent. */ inmessage.msg_controllen = sizeof(incmsg); error = test_recvmsg(sk2, &inmessage, MSG_WAITALL); test_check_msg_data(&inmessage, error, strlen(message) + 1, MSG_EOR, stream, ppid); /* Figure out how big to make our fillmsg */ len = sizeof(struct sctp_status); memset(&gstatus, 0, sizeof(struct sctp_status)); gstatus.sstat_assoc_id = associd1; error = getsockopt(sk1, IPPROTO_SCTP, SCTP_STATUS, &gstatus, &len); if (error) tst_brkm(TBROK, NULL, "can't get rwnd size: %s", strerror(errno)); tst_resm(TINFO, "Creating fillmsg of size %d", gstatus.sstat_rwnd + RWND_SLOP); fillmsg = malloc(gstatus.sstat_rwnd + RWND_SLOP); /* Send a fillmsg */ outmessage.msg_controllen = sizeof(outcmsg); outmessage.msg_flags = 0; cmsg = CMSG_FIRSTHDR(&outmessage); cmsg->cmsg_level = IPPROTO_SCTP; cmsg->cmsg_type = SCTP_SNDRCV; cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo)); outmessage.msg_controllen = cmsg->cmsg_len; sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg); memset(sinfo, 0x00, sizeof(struct sctp_sndrcvinfo)); ppid++; stream++; sinfo->sinfo_ppid = ppid; sinfo->sinfo_stream = stream; memset(fillmsg, 'X', gstatus.sstat_rwnd + RWND_SLOP); fillmsg[gstatus.sstat_rwnd + RWND_SLOP - 1] = '\0'; outmessage.msg_iov->iov_base = fillmsg; outmessage.msg_iov->iov_len = gstatus.sstat_rwnd + RWND_SLOP; outmessage.msg_name = NULL; outmessage.msg_namelen = 0; sinfo->sinfo_assoc_id = associd1; sinfo->sinfo_timetolive = 0; test_sendmsg(sk1, &outmessage, MSG_NOSIGNAL, gstatus.sstat_rwnd + RWND_SLOP); /* Now send the message with timeout. */ sinfo->sinfo_ppid = ppid; sinfo->sinfo_stream = stream; outmessage.msg_iov->iov_base = ttlmsg; outmessage.msg_iov->iov_len = strlen(ttlmsg) + 1; outmessage.msg_name = NULL; outmessage.msg_namelen = 0; sinfo->sinfo_assoc_id = associd1; sinfo->sinfo_timetolive = 2000; test_sendmsg(sk1, &outmessage, MSG_NOSIGNAL, strlen(ttlmsg) + 1); tst_resm(TPASS, "Send a message with timeout"); /* Next send a message with no timeout. */ sinfo->sinfo_ppid = ppid; sinfo->sinfo_stream = stream; outmessage.msg_iov->iov_base = nottlmsg; outmessage.msg_iov->iov_len = strlen(nottlmsg) + 1; outmessage.msg_name = NULL; outmessage.msg_namelen = 0; sinfo->sinfo_assoc_id = associd1; sinfo->sinfo_timetolive = 0; test_sendmsg(sk1, &outmessage, MSG_NOSIGNAL, strlen(nottlmsg) + 1); tst_resm(TPASS, "Send a message with no timeout"); /* And finally a fragmented message that will time out. */ sinfo->sinfo_ppid = ppid; sinfo->sinfo_stream = stream; memset(ttlfrag, '0', sizeof(ttlfrag)); ttlfrag[sizeof(ttlfrag) - 1] = '\0'; outmessage.msg_iov->iov_base = ttlfrag; outmessage.msg_iov->iov_len = sizeof(ttlfrag); outmessage.msg_name = NULL; outmessage.msg_namelen = 0; sinfo->sinfo_assoc_id = associd1; sinfo->sinfo_timetolive = 2000; test_sendmsg(sk1, &outmessage, MSG_NOSIGNAL, sizeof(ttlfrag)); tst_resm(TPASS, "Send a fragmented message with timeout"); /* Sleep waiting for the message to time out. */ tst_resm(TINFO, " ** SLEEPING for 3 seconds **"); sleep(3); /* Read the fillmsg snuck in between the ttl'd messages. */ do { inmessage.msg_controllen = sizeof(incmsg); error = test_recvmsg(sk2, &inmessage, MSG_WAITALL); } while (!(inmessage.msg_flags & MSG_EOR)); /* Now get the message that did NOT time out. */ inmessage.msg_controllen = sizeof(incmsg); error = test_recvmsg(sk2, &inmessage, MSG_WAITALL); test_check_msg_data(&inmessage, error, strlen(nottlmsg) + 1, MSG_EOR, stream, ppid); if (0 != strncmp(iov.iov_base, nottlmsg, strlen(nottlmsg) + 1)) tst_brkm(TBROK, NULL, "Received Wrong Message !!!"); tst_resm(TPASS, "Receive message with no timeout"); /* Get the SEND_FAILED notification for the message that DID * time out. */ inmessage.msg_controllen = sizeof(incmsg); error = test_recvmsg(sk1, &inmessage, MSG_WAITALL); test_check_msg_notification(&inmessage, error, sizeof(struct sctp_send_failed) + strlen(ttlmsg) + 1, SCTP_SEND_FAILED, 0); ssf = (struct sctp_send_failed *)iov.iov_base; if (0 != strncmp(ttlmsg, (char *)ssf->ssf_data, strlen(ttlmsg) + 1)) tst_brkm(TBROK, NULL, "SEND_FAILED data mismatch"); tst_resm(TPASS, "Receive SEND_FAILED for message with timeout"); /* Get the SEND_FAILED notification for the fragmented message that * DID time out. */ offset = 0; do { inmessage.msg_controllen = sizeof(incmsg); error = test_recvmsg(sk1, &inmessage, MSG_WAITALL); test_check_msg_notification(&inmessage, error, sizeof(struct sctp_send_failed) + SMALL_MAXSEG, SCTP_SEND_FAILED, 0); ssf = (struct sctp_send_failed *)iov.iov_base; if (0 != strncmp(&ttlfrag[offset], (char *)ssf->ssf_data, SMALL_MAXSEG)) tst_brkm(TBROK, NULL, "SEND_FAILED data mismatch"); offset += SMALL_MAXSEG; } while (!(ssf->ssf_info.sinfo_flags & 0x01)); /* LAST_FRAG */ tst_resm(TPASS, "Receive SEND_FAILED for fragmented message with " "timeout"); /* Shut down the link. */ close(sk1); /* Get the shutdown complete notification. */ inmessage.msg_controllen = sizeof(incmsg); error = test_recvmsg(sk2, &inmessage, MSG_WAITALL); test_check_msg_notification(&inmessage, error, sizeof(struct sctp_assoc_change), SCTP_ASSOC_CHANGE, SCTP_SHUTDOWN_COMP); close(sk2); /* Indicate successful completion. */ tst_exit(); }
int SP_ProcPduUtils :: send_fd (int sockfd, int fd) { struct msghdr msg; struct iovec iov[1]; #ifdef HAVE_MSGHDR_MSG_CONTROL union { struct cmsghdr cm; char control[CMSG_SPACE(sizeof(int))]; } control_un; struct cmsghdr *cmptr; msg.msg_control = control_un.control; msg.msg_controllen = sizeof(control_un.control); cmptr = CMSG_FIRSTHDR(&msg); cmptr->cmsg_len = CMSG_LEN(sizeof(int)); cmptr->cmsg_level = SOL_SOCKET; cmptr->cmsg_type = SCM_RIGHTS; *((int *) CMSG_DATA(cmptr)) = fd; #else msg.msg_accrights = (caddr_t) &fd; msg.msg_accrightslen = sizeof(int); #endif msg.msg_name = NULL; msg.msg_namelen = 0; char buf[1]; iov[0].iov_base = buf; iov[0].iov_len = 1; msg.msg_iov = iov; msg.msg_iovlen = 1; for( ; ; ) { errno = 0; if (sendmsg(sockfd, &msg, 0) != 1) { if( EINTR == errno ) { continue; } else { return -1; } } else { break; } } return 0; /* char tmpbuf[CONTROLLEN]; struct cmsghdr *cmptr = (struct cmsghdr *) tmpbuf; struct iovec iov[1]; struct msghdr msg; char buf[1]; iov[0].iov_base = buf; iov[0].iov_len = 1; msg.msg_iov = iov; msg.msg_iovlen = 1; msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_control = cmptr; msg.msg_controllen = CONTROLLEN; cmptr->cmsg_level = SOL_SOCKET; cmptr->cmsg_type = SCM_RIGHTS; cmptr->cmsg_len = CONTROLLEN; *(int *)CMSG_DATA (cmptr) = fd; for( ; ; ) { errno = 0; if (sendmsg(sockfd, &msg, 0) != 1) { if( EINTR == errno ) { continue; } else { return -1; } } else { break; } } return 0; */ }
int main_tls_client() { SSL_CTX *ctx; SSL *ssl; int server = 0; int ret; if ( (ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) printf("Unable to create a new SSL context structure.\n"); SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2); // Force gcm(aes) mode SSL_CTX_set_cipher_list(ctx, "ECDH-ECDSA-AES128-GCM-SHA256"); ssl = SSL_new(ctx); server = create_socket(); SSL_set_fd(ssl, server); if ( SSL_connect(ssl) != 1 ) { printf("Error: Could not build a SSL session\n"); exit(-1); } // Start tests clock_t start, end; double cpu_time_used; int filefd; int bytes; int totalbytes = 0; bytes_recv = 0; char buf[16384]; int res = 0; int total_recv = 0; start = clock(); filefd = open(test_data, O_RDONLY); totalbytes = 0; do { bytes = read(filefd, buf, sizeof(buf)); totalbytes += bytes; if (bytes > 0) SSL_write(ssl, buf, bytes); } while(bytes > 0); close(filefd); end = clock(); cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC; printf("OpenSSL receive time: %.02f\n", cpu_time_used); res = 0; total_recv = 0; res = SSL_read(ssl, buf, 1); total_recv += res; if (res < 0) { printf("SSL Read error: %i\n", res); } printf("Received openssl test data: %i %i\n", res, total_recv); /* Kernel TLS tests */ int tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0); if (tfmfd == -1) { perror("socket error:"); exit(-1); } struct sockaddr_alg sa = { .salg_family = AF_ALG, .salg_type = "tls", /* this selects the hash logic in the kernel */ .salg_name = "rfc5288(gcm(aes))" /* this is the cipher name */ }; if (bind(tfmfd, (struct sockaddr *)&sa, sizeof(sa)) == -1) { perror("AF_ALG: bind failed"); close(tfmfd); exit(-1); } int opfd = accept(tfmfd, NULL, 0); if (opfd == -1) { perror("accept:"); close(tfmfd); exit(-1); } if (setsockopt(tfmfd, SOL_ALG, ALG_SET_AEAD_AUTHSIZE, NULL, 16)) { perror("AF_ALG: set authsize failed\n"); exit(-1); } EVP_CIPHER_CTX * writeCtx = ssl->enc_write_ctx; EVP_CIPHER_CTX * readCtx = ssl->enc_read_ctx; EVP_AES_GCM_CTX* gcmWrite = (EVP_AES_GCM_CTX*)(writeCtx->cipher_data); EVP_AES_GCM_CTX* gcmRead = (EVP_AES_GCM_CTX*)(readCtx->cipher_data); unsigned char* writeKey = (unsigned char*)(gcmWrite->gcm.key); unsigned char* readKey = (unsigned char*)(gcmRead->gcm.key); unsigned char* writeIV = gcmWrite->iv; unsigned char* readIV = gcmRead->iv; char keyiv[20]; memcpy(keyiv, writeKey, 16); memcpy(keyiv + 16, writeIV, 4); if (setsockopt(tfmfd, SOL_ALG, ALG_SET_KEY, keyiv, 20)) { perror("AF_ALG: set write key failed\n"); exit(-1); } memcpy(keyiv, readKey, 16); memcpy(keyiv + 16, readIV, 4); if (setsockopt(tfmfd, SOL_ALG, ALG_SET_KEY, keyiv, 20)) { perror("AF_ALG: set read key failed\n"); exit(-1); } // Load up the cmsg data struct cmsghdr *header = NULL; uint32_t *type = NULL; struct msghdr msg; /* IV data */ struct af_alg_iv *alg_iv = NULL; int ivsize = 12; uint32_t iv_msg_size = CMSG_SPACE(sizeof(*alg_iv) + ivsize); /* AEAD data */ uint32_t *assoclen = NULL; uint32_t assoc_msg_size = CMSG_SPACE(sizeof(*assoclen)); uint32_t bufferlen = CMSG_SPACE(sizeof(*type)) + /* Encryption / Decryption */ iv_msg_size +/* IV */ assoc_msg_size;/* AEAD associated data size */ memset(&msg, 0, sizeof(msg)); char* buffer = calloc(1, bufferlen); if (!buffer) return -ENOMEM; msg.msg_control = buffer; msg.msg_controllen = bufferlen; msg.msg_iov = NULL; msg.msg_iovlen = 0; /* encrypt/decrypt operation */ header = CMSG_FIRSTHDR(&msg); header->cmsg_level = SOL_ALG; header->cmsg_type = ALG_SET_OP; header->cmsg_len = CMSG_LEN(sizeof(*type)); type = (void*)CMSG_DATA(header); *type = server; /* set IV */ header = CMSG_NXTHDR(&msg, header); header->cmsg_level = SOL_ALG; header->cmsg_type = ALG_SET_IV; header->cmsg_len = iv_msg_size; alg_iv = (void*)CMSG_DATA(header); alg_iv->ivlen = 8; uint64_t writeSeq; unsigned char* writeSeqNum = ssl->s3->write_sequence; memcpy(&writeSeq, writeSeqNum, sizeof(writeSeq)); memcpy(alg_iv->iv, &writeSeq, 8); /* set AEAD information */ /* Set associated data length */ header = CMSG_NXTHDR(&msg, header); header->cmsg_level = SOL_ALG; header->cmsg_type = ALG_SET_AEAD_ASSOCLEN; header->cmsg_len = CMSG_LEN(sizeof(*assoclen)); assoclen = (void*)CMSG_DATA(header); *assoclen = 13 + 8; ret = sendmsg(opfd, &msg, MSG_MORE); if (ret < 0) { perror("sendmsg"); exit(-1); } header = CMSG_FIRSTHDR(&msg); header = CMSG_NXTHDR(&msg, header); alg_iv = (void*)CMSG_DATA(header); uint64_t readSeq; unsigned char* readSeqNum = ssl->s3->read_sequence; memcpy(&readSeq, readSeqNum, sizeof(readSeq)); memcpy(alg_iv->iv, &readSeq, 8); ret = sendmsg(opfd, &msg, MSG_MORE); if (ret < 0) { perror("sendmsg recv"); exit(-1); } // Try some simple writes send(opfd, buf, 10, 0); send(opfd, buf, 100, 0); send(opfd, buf, 16000, 0); printf("Successful send\n"); res = 0; total_recv = 0; res = recv(opfd, &buf, 1, 0); total_recv += res; if (res < 0) { printf("Ktls recv error: %i\n", res); } printf("Recvd ktls test data: %i %i\n", res, total_recv); start = clock(); off_t offset = 0; filefd = open(test_data, O_RDONLY); res = sendfile(opfd, filefd, &offset, totalbytes); close(filefd); end = clock(); cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC; printf("ktls receive time: %.02f\n", cpu_time_used); SSL_free(ssl); close(server); SSL_CTX_free(ctx); return(0); } int OpenListener(int port) { int sd; struct sockaddr_in6 addr; sd = socket(PF_INET6, SOCK_STREAM, 0); bzero(&addr, sizeof(addr)); addr.sin6_family = AF_INET6; addr.sin6_port = htons(port); memcpy(addr.sin6_addr.s6_addr, &in6addr_any, sizeof(in6addr_any)); if ( bind(sd, (const struct sockaddr*)&addr, sizeof(addr)) != 0 ) { perror("can't bind port"); abort(); } if ( listen(sd, 10) != 0 ) { perror("Can't configure listening port"); abort(); } return sd; }
int recv_fd(int fd,ssize_t (*userfunc)(int,const void *,size_t)) { int newfd,nr,status; char *ptr; char buf[magicnum::localsocketfun::BUFFERSIZE]; struct iovec iov[1]; struct msghdr msg; status=-1; for(;;) { iov[0].iov_base=buf; iov[0].iov_len=sizeof(buf); msg.msg_iov=iov; msg.msg_iovlen=1; msg.msg_name=NULL; msg.msg_namelen=0; if(cmptr==NULL&&(cmptr=(cmsghdr*)malloc(CONTROLLEN))==NULL) { return magicnum::FAILIED; } msg.msg_control=cmptr; msg.msg_controllen=CONTROLLEN; if((nr=recvmsg(fd,&msg,0))<0) { if(errno == EAGAIN || errno == EINTR)//EAGAIN:缓存无数据;EINTR:系统中断 { //printf("buffer no data\n");//缓存区已无数据可读 //readbytes = 0; continue; } perror("recvmsg"); //perror("recv"); return magicnum::FAILIED; } else if(nr==0) { printf("connection closed by server\n"); return magicnum::FAILIED; } for(ptr=buf;ptr<&buf[nr];) { if(*ptr++==0){ assert(ptr == &buf[nr-1]); status=*ptr&0xFF; if(status==0) { if(msg.msg_controllen!=CONTROLLEN) { printf("status=0,but no fd\n"); return magicnum::FAILIED; } newfd=*(int*)CMSG_DATA(cmptr); } else { newfd=-status; } nr=-2; } } if(nr > 0 && (*userfunc)(STDERR_FILENO,buf,nr)!=nr) { return magicnum::FAILIED; } if(status>=0) { return(newfd); } } }
int J1939SocketRead (int Socket, struct J1939FrameBag *Bags, unsigned int BagsCount, int TimeoutMs) { struct mmsghdr msgs[BagsCount]; struct iovec iovs[BagsCount]; struct sockaddr_can addr[BagsCount]; char ctrlmsgs[BagsCount][ CMSG_SPACE(sizeof(struct timeval)) + CMSG_SPACE(sizeof(__u8)) /* dest addr */ + CMSG_SPACE(sizeof(__u64)) /* dest name */ + CMSG_SPACE(sizeof(__u8)) /* priority */ ]; unsigned int i; for (i = 0; i < BagsCount; i++) { memset(&msgs[i], 0, sizeof(msgs[0])); memset(&iovs[i], 0, sizeof(iovs[0])); memset(&addr[i], 0, sizeof(addr[0])); msgs[i].msg_hdr.msg_name = &addr[i]; msgs[i].msg_hdr.msg_namelen = sizeof(struct sockaddr_can); iovs[i].iov_base = (void *) &(Bags[i].Frame.data); iovs[i].iov_len = sizeof(Bags[i].Frame.data); msgs[i].msg_hdr.msg_iov = &iovs[i]; msgs[i].msg_hdr.msg_iovlen = 1; msgs[i].msg_hdr.msg_control = &ctrlmsgs[i]; msgs[i].msg_hdr.msg_controllen = sizeof(ctrlmsgs[0]); msgs[i].msg_hdr.msg_flags = 0; } struct timeval tNow, tEnd; for ( initTimers(&tNow, &tEnd, TimeoutMs); timercmp(&tNow, &tEnd, <); gettimeofday (&tNow, NULL) ) { int rcount; rcount = recvmmsg(Socket, msgs, BagsCount, MSG_DONTWAIT, NULL); if (rcount >= 0) { int i; for (i = 0; i < rcount; i ++) { struct timeval tv; struct cmsghdr *cmsg; for (cmsg = CMSG_FIRSTHDR(&msgs[i].msg_hdr); cmsg; cmsg = CMSG_NXTHDR(&msgs[i].msg_hdr,cmsg)) { switch (cmsg->cmsg_level) { case SOL_SOCKET: if (cmsg->cmsg_type == SO_TIMESTAMP) { tv = *(struct timeval *)CMSG_DATA(cmsg); Bags[i].TimeStamp.seconds = tv.tv_sec; Bags[i].TimeStamp.microseconds = tv.tv_usec; } else if (cmsg->cmsg_type == SO_RXQ_OVFL) Bags[i].DroppedMessagesCount = *(__u32 *)CMSG_DATA(cmsg); break; case SOL_CAN_J1939: break; } } Bags[i].Frame.pgn = addr[i].can_addr.j1939.pgn; Bags[i].Frame.length = msgs[i].msg_len; if (msgs[i].msg_hdr.msg_flags & MSG_CONFIRM) Bags[i].Flags |= (1 << 0); } return rcount; } else { int errsv = errno; if (errsv == EAGAIN) continue; else return errsv; } } return 0; }
int main(int argc, char *argv[]) { struct msghdr msgh; struct iovec iov; int data, sfd, opt, fd; ssize_t ns; Boolean useDatagramSocket; union { struct cmsghdr cmh; char control[CMSG_SPACE(sizeof(int))]; /* Space large enough to hold an 'int' */ } control_un; struct cmsghdr *cmhp; /* Parse command-line arguments */ useDatagramSocket = FALSE; while ((opt = getopt(argc, argv, "d")) != -1) { switch (opt) { case 'd': useDatagramSocket = TRUE; break; default: usageErr("%s [-d] file\n" " -d use datagram socket\n", argv[0]); } } if (argc != optind + 1) usageErr("%s [-d] file\n", argv[0]); /* Open the file named on the command line */ fd = open(argv[optind], O_RDONLY); if (fd == -1) errExit("open"); /* On Linux, we must transmit at least 1 byte of real data in order to send ancillary data */ msgh.msg_iov = &iov; msgh.msg_iovlen = 1; iov.iov_base = &data; iov.iov_len = sizeof(int); data = 12345; /* We don't need to specify destination address, because we use connect() below */ msgh.msg_name = NULL; msgh.msg_namelen = 0; msgh.msg_control = control_un.control; msgh.msg_controllen = sizeof(control_un.control); fprintf(stderr, "Sending fd %d\n", fd); /* Set message header to describe ancillary data that we want to send */ cmhp = CMSG_FIRSTHDR(&msgh); cmhp->cmsg_len = CMSG_LEN(sizeof(int)); cmhp->cmsg_level = SOL_SOCKET; cmhp->cmsg_type = SCM_RIGHTS; *((int *) CMSG_DATA(cmhp)) = fd; /* We could rewrite the preceding lines as: control_un.cmh.cmsg_len = CMSG_LEN(sizeof(int)); control_un.cmh.cmsg_level = SOL_SOCKET; control_un.cmh.cmsg_type = SCM_RIGHTS; *((int *) CMSG_DATA(CMSG_FIRSTHDR(&msgh))) = fd; */ /* Do the actual send */ sfd = unixConnect(SOCK_PATH, useDatagramSocket ? SOCK_DGRAM : SOCK_STREAM); if (sfd == -1) errExit("unixConnect"); ns = sendmsg(sfd, &msgh, 0); if (ns == -1) errExit("sendmsg"); fprintf(stderr, "sendmsg() returned %ld\n", (long) ns); exit(EXIT_SUCCESS); }
const char * format_extended_socket_error (int fd, int *mtu, struct gc_arena *gc) { int res; struct probehdr rcvbuf; struct iovec iov; struct msghdr msg; struct cmsghdr *cmsg; struct sock_extended_err *e; struct sockaddr_in addr; struct buffer out = alloc_buf_gc (256, gc); char *cbuf = (char *) gc_malloc (256, false, gc); *mtu = 0; while (true) { memset (&rcvbuf, -1, sizeof (rcvbuf)); iov.iov_base = &rcvbuf; iov.iov_len = sizeof (rcvbuf); msg.msg_name = (uint8_t *) &addr; msg.msg_namelen = sizeof (addr); msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_flags = 0; msg.msg_control = cbuf; msg.msg_controllen = 256; /* size of cbuf */ res = recvmsg (fd, &msg, MSG_ERRQUEUE); if (res < 0) goto exit; e = NULL; for (cmsg = CMSG_FIRSTHDR (&msg); cmsg; cmsg = CMSG_NXTHDR (&msg, cmsg)) { if (cmsg->cmsg_level == SOL_IP) { if (cmsg->cmsg_type == IP_RECVERR) { e = (struct sock_extended_err *) CMSG_DATA (cmsg); } else { buf_printf (&out ,"CMSG=%d|", cmsg->cmsg_type); } } } if (e == NULL) { buf_printf (&out, "NO-INFO|"); goto exit; } switch (e->ee_errno) { case ETIMEDOUT: buf_printf (&out, "ETIMEDOUT|"); break; case EMSGSIZE: buf_printf (&out, "EMSGSIZE Path-MTU=%d|", e->ee_info); *mtu = e->ee_info; break; case ECONNREFUSED: buf_printf (&out, "ECONNREFUSED|"); break; case EPROTO: buf_printf (&out, "EPROTO|"); break; case EHOSTUNREACH: buf_printf (&out, "EHOSTUNREACH|"); break; case ENETUNREACH: buf_printf (&out, "ENETUNREACH|"); break; case EACCES: buf_printf (&out, "EACCES|"); break; default: buf_printf (&out, "UNKNOWN|"); break; } } exit: buf_rmtail (&out, '|'); return BSTR (&out); }
int main(int ac,char **av) { struct msghdr msghdr; struct iovec iovector[10]; int i,s,j,ma; struct sockaddr_in sockad; char msg[128]; struct cmsghdr *cmsg,*cm2; char opts[24]; ma=250; printf("just wait and watch memory usage\n"); memset(opts,0,sizeof(opts)); while(42) { s=socket(PF_INET, /*SOCK_STREAM*/ SOCK_DGRAM, 0); sockad.sin_family = AF_INET; sockad.sin_addr.s_addr=inet_addr("127.0.0.1"); sockad.sin_port=htons(8080); connect(s,(struct sockaddr *) &sockad, sizeof(sockad)); memset(msg,'v',sizeof(msg)); #define VV (ma*(sizeof(struct cmsghdr)+sizeof(opts))+1024*1024) cmsg = malloc(VV); memset(cmsg,0,VV); cmsg->cmsg_len = sizeof(struct cmsghdr) + sizeof(opts); cmsg->cmsg_level = SOL_IP; cmsg->cmsg_type = IP_RETOPTS; memcpy(CMSG_DATA(cmsg), opts, sizeof(opts)); cm2= (struct cmsghdr *) (long) ((char *)CMSG_DATA(cmsg)+sizeof(opts)); for(j=0;j<ma;j++) { cm2->cmsg_level = SOL_IP; cm2->cmsg_type = IP_RETOPTS; cm2->cmsg_len = sizeof(struct cmsghdr) + sizeof(opts); cm2= (struct cmsghdr *) (long) ((char *)CMSG_DATA(cm2)+sizeof(opts)); } cm2->cmsg_level = SOL_IP; cm2->cmsg_type = IP_RETOPTS; cm2->cmsg_len = sizeof(struct cmsghdr) + 8; msghdr.msg_name = &sockad; msghdr.msg_namelen = sizeof(sockad); msghdr.msg_control=cmsg; msghdr.msg_controllen= cmsg->cmsg_len + (j)*cmsg->cmsg_len+cm2->cmsg_len; msghdr.msg_iov = iovector; msghdr.msg_iovlen = 1; iovector[0].iov_base = msg; iovector[0].iov_len = sizeof(msg); if ((i = sendmsg(s, &msghdr, 0)) < 0) {perror("sendmsg");return -42;} close(s); free(cmsg); } return 42; }
/* * Read a message from the specified connection carrying file descriptors */ int pool_recvfds(PoolPort *port, int *fds, int count) { int r; uint n32; char buf[SEND_MSG_BUFFER_SIZE]; struct iovec iov[1]; struct msghdr msg; int controllen = CMSG_LEN(count * sizeof(int)); struct cmsghdr *cmptr = malloc(CMSG_SPACE(count * sizeof(int))); if (cmptr == NULL) return EOF; iov[0].iov_base = buf; iov[0].iov_len = SEND_MSG_BUFFER_SIZE; msg.msg_iov = iov; msg.msg_iovlen = 1; msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_control = (caddr_t) cmptr; msg.msg_controllen = controllen; r = recvmsg(Socket(*port), &msg, 0); if (r < 0) { /* * Report broken connection */ ereport(ERROR, (errcode_for_socket_access(), errmsg("could not receive data from client: %m"))); goto failure; } else if (r == 0) { goto failure; } else if (r != SEND_MSG_BUFFER_SIZE) { ereport(ERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("incomplete message from client [size: %u errno %u]",r,errno))); goto failure; } /* Verify response */ if (buf[0] != 'f') { ereport(ERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("unexpected message code"))); goto failure; } memcpy(&n32, buf + 1, 4); n32 = ntohl(n32); if (n32 != 8) { ereport(ERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("invalid message size"))); goto failure; } /* * If connection count is 0 it means pool does not have connections * to fulfill request. Otherwise number of returned connections * should be equal to requested count. If it not the case consider this * a protocol violation. (Probably connection went out of sync) */ memcpy(&n32, buf + 5, 4); n32 = ntohl(n32); if (n32 == 0) { ereport(LOG, (errcode(ERRCODE_INSUFFICIENT_RESOURCES), errmsg("failed to acquire connections"))); goto failure; } if (n32 != count) { ereport(ERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("unexpected connection count"))); goto failure; } memcpy(fds, CMSG_DATA(CMSG_FIRSTHDR(&msg)), count * sizeof(int)); free(cmptr); return 0; failure: free(cmptr); return EOF; }
//RY: start here void network_thread_IPv6() { /* * We loop forever waiting on either data from the ppp drivers or from * our network socket. Control handling is no longer done here. */ struct sockaddr_in6 from, to; unsigned int fromlen, tolen; int tunnel, call; /* Tunnel and call */ int recvsize; /* Length of data received */ struct buffer6 *buf; /* Payload buffer */ struct call6 *c, *sc; /* Call to send this off to */ struct tunnel6 *st; /* Tunnel */ fd_set readfds; /* Descriptors to watch for reading */ int max; /* Highest fd */ struct timeval tv; /* Timeout for select */ struct msghdr msgh; struct iovec iov; char cbuf[256]; unsigned int refme, refhim; /* This one buffer can be recycled for everything except control packets */ buf = new_buf6 (MAX_RECV_SIZE); tunnel = 0; call = 0; for (;;) { max = build_fdset_ipv6 (&readfds); tv.tv_sec = 1;//RY:commented for testing //tv.tv_sec = 0;//RY: made 0 for testing, anyways not being used in select(). tv.tv_usec = 0; schedule_unlock (); // RY: start #if 0 buf->peer = from; buf->len = sizeof(from); buf->start = NULL; udp_xmit6 (buf, st); udp_xmit6 (buf, st); udp_xmit6 (buf, st); #endif //RY: end select (max + 1, &readfds, NULL, NULL, NULL); schedule_lock (); if (FD_ISSET (control_fd, &readfds)) { do_control6 (); } //TODO: Mistake prone line.RY: if (FD_ISSET (server_socket6, &readfds)) { /* * Okay, now we're ready for reading and processing new data. */ recycle_buf6 (buf); /* Reserve space for expanding payload packet headers */ buf->start += PAYLOAD_BUF; buf->len -= PAYLOAD_BUF; memset(&from, 0, sizeof(from)); memset(&to, 0, sizeof(to)); fromlen = sizeof(from); tolen = sizeof(to); memset(&msgh, 0, sizeof(struct msghdr)); iov.iov_base = buf->start; iov.iov_len = buf->len; msgh.msg_control = cbuf; msgh.msg_controllen = sizeof(cbuf); msgh.msg_name = &from; msgh.msg_namelen = fromlen; msgh.msg_iov = &iov; msgh.msg_iovlen = 1; msgh.msg_flags = 0; //RY: start here /* Receive one packet. */ recvsize = recvmsg(server_socket6, &msgh, 0); //RY: ends here if (recvsize < MIN_PAYLOAD_HDR_LEN) { if (recvsize < 0) { if (errno != EAGAIN) l2tp_log (LOG_WARNING, "%s: recvfrom returned error %d (%s)\n", __FUNCTION__, errno, strerror (errno)); } else { l2tp_log (LOG_WARNING, "%s: received too small a packet\n", __FUNCTION__); } continue; } refme=refhim=0; /* extract IPsec info out */ if(gconfig.ipsecsaref) { struct cmsghdr *cmsg; /* Process auxiliary received data in msgh */ for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL; cmsg = CMSG_NXTHDR(&msgh,cmsg)) { if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IP_IPSEC_REFINFO) { //RY: can be changed to unsigned int *refp; refp = (unsigned int *)CMSG_DATA(cmsg); refme =refp[0]; refhim=refp[1]; } } } /* * some logic could be added here to verify that we only * get L2TP packets inside of IPsec, or to provide different * classes of service to packets not inside of IPsec. */ buf->len = recvsize; fix_hdr (buf->start); extract (buf->start, &tunnel, &call); if (gconfig.debug_network) { //RY: start //TODO: un-comment later.. l2tp_log(LOG_DEBUG, "RY: packet received"); // l2tp_log(LOG_DEBUG, "%s: recv packet from %s, size = %d, " // "tunnel = %d, call = %d ref=%u refhim=%u\n", // __FUNCTION__, inet_ntop(from.sin6_addr), // recvsize, tunnel, call, refme, refhim); //RY: end } if (gconfig.packet_dump) { do_packet_dump6 (buf); } if (! (c = get_call6 (tunnel, call, from.sin6_addr, from.sin6_port, refme, refhim))) { if ((c = get_tunnel6 (tunnel, from.sin6_port))) { /* * It is theoretically possible that we could be sent * a control message (say a StopCCN) on a call that we * have already closed or some such nonsense. To * prevent this from closing the tunnel, if we get a * call on a valid tunnel, but not with a valid CID, * we'll just send a ZLB to ack receiving the packet. */ if (gconfig.debug_tunnel) l2tp_log (LOG_DEBUG, "%s: no such call %d on tunnel %d. Sending special ZLB\n", __FUNCTION__); handle_special6 (buf, c, call); /* get a new buffer */ buf = new_buf6 (MAX_RECV_SIZE); } else l2tp_log (LOG_DEBUG, "%s: unable to find call or tunnel to handle packet. call = %d, tunnel = %d Dumping.\n", __FUNCTION__, call, tunnel); } else { buf->peer = from; /* Handle the packet */ c->container->chal_us.vector = NULL; if (handle_packet6 (buf, c->container, c)) { if (gconfig.debug_tunnel) l2tp_log (LOG_DEBUG, "%s: bad packet\n", __FUNCTION__); } if (c->cnu) { /* Send Zero Byte Packet */ control_zlb6 (buf, c->container, c); c->cnu = 0; } } } /* * finished obvious sources, look for data from PPP connections. */ st = tunnels6.head; while (st) { sc = st->call_head; while (sc) { if ((sc->fd >= 0) && FD_ISSET (sc->fd, &readfds)) { /* Got some payload to send */ int result; recycle_payload6 (buf, sc->container->peer); /* #ifdef DEBUG_FLOW_MORE l2tp_log (LOG_DEBUG, "%s: rws = %d, pSs = %d, pLr = %d\n", __FUNCTION__, sc->rws, sc->pSs, sc->pLr); #endif if ((sc->rws>0) && (sc->pSs > sc->pLr + sc->rws) && !sc->rbit) { #ifdef DEBUG_FLOW log(LOG_DEBUG, "%s: throttling payload (call = %d, tunnel = %d, Lr = %d, Ss = %d, rws = %d)!\n",__FUNCTION__, sc->cid, sc->container->tid, sc->pLr, sc->pSs, sc->rws); #endif sc->throttle = -1; We unthrottle in handle_packet if we get a payload packet, valid or ZLB, but we also schedule a dethrottle in which case the R-bit will be set FIXME: Rate Adaptive timeout? tv.tv_sec = 2; tv.tv_usec = 0; sc->dethrottle = schedule(tv, dethrottle, sc); } else */ /* while ((result=read_packet(buf,sc->fd,sc->frame & SYNC_FRAMING))>0) { */ while ((result = read_packet6 (buf, sc->fd, SYNC_FRAMING)) > 0) { add_payload_hdr6 (sc->container, sc, buf); if (gconfig.packet_dump) { do_packet_dump6 (buf); } sc->prx = sc->data_rec_seq_num; if (sc->zlb_xmit6) { deschedule (sc->zlb_xmit6); sc->zlb_xmit6 = NULL; } sc->tx_bytes += buf->len; sc->tx_pkts++; udp_xmit6 (buf, st); recycle_payload6 (buf, sc->container->peer); } if (result != 0) { l2tp_log (LOG_WARNING, "%s: tossing read packet, error = %s (%d). Closing call.\n", __FUNCTION__, strerror (-result), -result); strcpy (sc->errormsg, strerror (-result)); sc->needclose = -1; } } sc = sc->next; } st = st->next; } } }
static int NaClDescConnCapFdConnectAddr(struct NaClDesc *vself, struct NaClDesc **out_desc) { struct NaClDescConnCapFd *self = (struct NaClDescConnCapFd *) vself; NaClHandle sock_pair[2]; struct NaClDescImcDesc *connected_socket; char control_buf[CMSG_SPACE_KHANDLE_COUNT_MAX_INTS]; struct iovec iovec; struct msghdr connect_msg; struct cmsghdr *cmsg; int sent; int retval; assert(CMSG_SPACE(sizeof(int)) <= CMSG_SPACE_KHANDLE_COUNT_MAX_INTS); sock_pair[0] = NACL_INVALID_HANDLE; sock_pair[1] = NACL_INVALID_HANDLE; connected_socket = (struct NaClDescImcDesc *) NULL; retval = -NACL_ABI_EINVAL; if (0 != NaClSocketPair(sock_pair)) { retval = -NACL_ABI_EMFILE; goto cleanup; } iovec.iov_base = "c"; iovec.iov_len = 1; connect_msg.msg_iov = &iovec; connect_msg.msg_iovlen = 1; connect_msg.msg_name = NULL; connect_msg.msg_namelen = 0; connect_msg.msg_control = control_buf; connect_msg.msg_controllen = sizeof(control_buf); connect_msg.msg_flags = 0; cmsg = CMSG_FIRSTHDR(&connect_msg); cmsg->cmsg_len = CMSG_LEN(sizeof(int)); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; /* * We use memcpy() rather than assignment through a cast to avoid * strict-aliasing warnings */ memcpy(CMSG_DATA(cmsg), &sock_pair[0], sizeof(int)); /* Set msg_controllen to the actual size of the cmsg. */ connect_msg.msg_controllen = cmsg->cmsg_len; sent = sendmsg(self->connect_fd, &connect_msg, 0); if (1 != sent) { retval = -NACL_ABI_EIO; goto cleanup; } if (NACL_OSX) { /* * Mac OS X has a kernel bug in which a socket descriptor that is * referenced only from the message queue of another socket can * get garbage collected. This causes the socket descriptor not * to work properly. To work around this, we don't close our * reference to the socket until we receive an acknowledgement * that it has been successfully received. * * We cannot receive the acknowledgement through self->connect_fd * because this FD could be shared between multiple processes. So * we receive the acknowledgement through the socket pair that we * have just created. * * However, this creates a risk that we are left hanging if the * other process dies after our sendmsg() call, because we are * holding on to the socket that it would use to send the ack. To * avoid this problem, we use poll() so that we will be notified * if self->connect_fd becomes unwritable. * TODO(mseaborn): Add a test case to simulate that scenario. * * See http://code.google.com/p/nativeclient/issues/detail?id=1796 * * Note that we are relying on a corner case of poll() here. * Using POLLHUP in "events" is not meaningful on Linux, which is * documented as ignoring POLLHUP as an input argument and will * return POLLHUP in "revents" even if it not present in "events". * On Mac OS X, however, passing events == 0 does not work if we * want to get POLLHUP. We are in the unusual situation of * waiting for a socket to become *un*writable. */ struct pollfd poll_fds[2]; poll_fds[0].fd = self->connect_fd; poll_fds[0].events = POLLHUP; poll_fds[1].fd = sock_pair[1]; poll_fds[1].events = POLLIN; if (poll(poll_fds, 2, -1) < 0) { NaClLog(LOG_ERROR, "NaClDescConnCapFdConnectAddr: poll() failed, errno %d\n", errno); retval = -NACL_ABI_EIO; goto cleanup; } /* * It is not necessarily an error if POLLHUP fires on * self->connect_fd: The other process could have done * imc_accept(S) and then closed S. This means it will have * received sock_pair[0] successfully, so we can close our * reference to sock_pair[0] and then receive the ack. * TODO(mseaborn): Add a test case to cover this scenario. */ } (void) NaClClose(sock_pair[0]); sock_pair[0] = NACL_INVALID_HANDLE; if (NACL_OSX) { /* Receive the acknowledgement. We do not expect this to block. */ char ack_buffer[1]; ssize_t received = recv(sock_pair[1], ack_buffer, sizeof(ack_buffer), 0); if (received != 1 || ack_buffer[0] != 'a') { retval = -NACL_ABI_EIO; goto cleanup; } } connected_socket = malloc(sizeof(*connected_socket)); if (NULL == connected_socket || !NaClDescImcDescCtor(connected_socket, sock_pair[1])) { retval = -NACL_ABI_ENOMEM; goto cleanup; } sock_pair[1] = NACL_INVALID_HANDLE; *out_desc = (struct NaClDesc *) connected_socket; connected_socket = NULL; retval = 0; cleanup: NaClSafeCloseNaClHandle(sock_pair[0]); NaClSafeCloseNaClHandle(sock_pair[1]); free(connected_socket); return retval; }
void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm) { struct cmsghdr __user *cm = (__force struct cmsghdr __user*)msg->msg_control; int fdmax = 0; int fdnum = scm->fp->count; struct file **fp = scm->fp->fp; int __user *cmfptr; int err = 0, i; if (MSG_CMSG_COMPAT & msg->msg_flags) { scm_detach_fds_compat(msg, scm); return; } if (msg->msg_controllen > sizeof(struct cmsghdr)) fdmax = ((msg->msg_controllen - sizeof(struct cmsghdr)) / sizeof(int)); if (fdnum < fdmax) fdmax = fdnum; for (i=0, cmfptr=(__force int __user *)CMSG_DATA(cm); i<fdmax; i++, cmfptr++) { int new_fd; err = security_file_receive(fp[i]); if (err) break; err = get_unused_fd_flags(MSG_CMSG_CLOEXEC & msg->msg_flags ? O_CLOEXEC : 0); if (err < 0) break; new_fd = err; err = put_user(new_fd, cmfptr); if (err) { put_unused_fd(new_fd); break; } /* Bump the usage count and install the file. */ get_file(fp[i]); fd_install(new_fd, fp[i]); } if (i > 0) { int cmlen = CMSG_LEN(i*sizeof(int)); err = put_user(SOL_SOCKET, &cm->cmsg_level); if (!err) err = put_user(SCM_RIGHTS, &cm->cmsg_type); if (!err) err = put_user(cmlen, &cm->cmsg_len); if (!err) { cmlen = CMSG_SPACE(i*sizeof(int)); msg->msg_control += cmlen; msg->msg_controllen -= cmlen; } } if (i < fdnum || (fdnum && fdmax <= 0)) msg->msg_flags |= MSG_CTRUNC; /* * All of the files that fit in the message have had their * usage counts incremented, so we just free the list. */ __scm_destroy(scm); }
static void uv__read(uv_stream_t* stream) { uv_buf_t buf; ssize_t nread; struct msghdr msg; struct cmsghdr* cmsg; char cmsg_space[64]; struct ev_loop* ev = stream->loop->ev; /* XXX: Maybe instead of having UV_READING we just test if * tcp->read_cb is NULL or not? */ while ((stream->read_cb || stream->read2_cb) && stream->flags & UV_READING) { assert(stream->alloc_cb); buf = stream->alloc_cb((uv_handle_t*)stream, 64 * 1024); assert(buf.len > 0); assert(buf.base); assert(stream->fd >= 0); if (stream->read_cb) { do { nread = read(stream->fd, buf.base, buf.len); } while (nread < 0 && errno == EINTR); } else { assert(stream->read2_cb); /* read2_cb uses recvmsg */ msg.msg_flags = 0; msg.msg_iov = (struct iovec*) &buf; msg.msg_iovlen = 1; msg.msg_name = NULL; msg.msg_namelen = 0; /* Set up to receive a descriptor even if one isn't in the message */ msg.msg_controllen = 64; msg.msg_control = (void *) cmsg_space; do { nread = recvmsg(stream->fd, &msg, 0); } while (nread < 0 && errno == EINTR); } if (nread < 0) { /* Error */ if (errno == EAGAIN) { /* Wait for the next one. */ if (stream->flags & UV_READING) { ev_io_start(ev, &stream->read_watcher); } uv__set_sys_error(stream->loop, EAGAIN); if (stream->read_cb) { stream->read_cb(stream, 0, buf); } else { stream->read2_cb((uv_pipe_t*)stream, 0, buf, UV_UNKNOWN_HANDLE); } return; } else { /* Error. User should call uv_close(). */ uv__set_sys_error(stream->loop, errno); if (stream->read_cb) { stream->read_cb(stream, -1, buf); } else { stream->read2_cb((uv_pipe_t*)stream, -1, buf, UV_UNKNOWN_HANDLE); } assert(!ev_is_active(&stream->read_watcher)); return; } } else if (nread == 0) { /* EOF */ uv__set_artificial_error(stream->loop, UV_EOF); ev_io_stop(ev, &stream->read_watcher); if (stream->read_cb) { stream->read_cb(stream, -1, buf); } else { stream->read2_cb((uv_pipe_t*)stream, -1, buf, UV_UNKNOWN_HANDLE); } return; } else { /* Successful read */ ssize_t buflen = buf.len; if (stream->read_cb) { stream->read_cb(stream, nread, buf); } else { assert(stream->read2_cb); /* * XXX: Some implementations can send multiple file descriptors in a * single message. We should be using CMSG_NXTHDR() to walk the * chain to get at them all. This would require changing the API to * hand these back up the caller, is a pain. */ for (cmsg = CMSG_FIRSTHDR(&msg); msg.msg_controllen > 0 && cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) { if (cmsg->cmsg_type == SCM_RIGHTS) { if (stream->accepted_fd != -1) { fprintf(stderr, "(libuv) ignoring extra FD received\n"); } stream->accepted_fd = *(int *) CMSG_DATA(cmsg); } else { fprintf(stderr, "ignoring non-SCM_RIGHTS ancillary data: %d\n", cmsg->cmsg_type); } } if (stream->accepted_fd >= 0) { stream->read2_cb((uv_pipe_t*)stream, nread, buf, UV_TCP); } else { stream->read2_cb((uv_pipe_t*)stream, nread, buf, UV_UNKNOWN_HANDLE); } } /* Return if we didn't fill the buffer, there is no more data to read. */ if (nread < buflen) { return; } } } }