void FAST_FUNC read_leases(const char *file) { struct dyn_lease lease; int64_t written_at, time_passed; int fd; #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1 unsigned i = 0; #endif fd = open_or_warn(file, O_RDONLY); if (fd < 0) return; if (full_read(fd, &written_at, sizeof(written_at)) != sizeof(written_at)) goto ret; written_at = SWAP_BE64(written_at); time_passed = time(NULL) - written_at; /* Strange written_at, or lease file from old version of udhcpd * which had no "written_at" field? */ if ((uint64_t)time_passed > 12 * 60 * 60) goto ret; while (full_read(fd, &lease, sizeof(lease)) == sizeof(lease)) { uint32_t y = ntohl(lease.lease_nip); if (y >= server_config.start_ip && y <= server_config.end_ip) { signed_leasetime_t expires = ntohl(lease.expires) - (signed_leasetime_t)time_passed; uint32_t static_nip; if (expires <= 0) /* We keep expired leases: add_lease() will add * a lease with 0 seconds remaining. * Fewer IP address changes this way for mass reboot scenario. */ expires = 0; /* Check if there is a different static lease for this IP or MAC */ static_nip = get_static_nip_by_mac(server_config.static_leases, lease.lease_mac); if (static_nip) { /* NB: we do not add lease even if static_nip == lease.lease_nip. */ continue; } if (is_nip_reserved(server_config.static_leases, lease.lease_nip)) continue; /* NB: add_lease takes "relative time", IOW, * lease duration, not lease deadline. */ if (add_lease(lease.lease_mac, lease.lease_nip, expires, lease.hostname, sizeof(lease.hostname) ) == 0 ) { bb_error_msg("too many leases while loading %s", file); break; } #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1 i++; #endif } } log1("read %d leases", i); ret: close(fd); }
void RTCPInstance::incomingReportHandler1() { do { Boolean callByeHandler = False; int tcpReadStreamSocketNum = fRTCPInterface.nextTCPReadStreamSocketNum(); unsigned char tcpReadStreamChannelId = fRTCPInterface.nextTCPReadStreamChannelId(); unsigned packetSize = 0; unsigned numBytesRead; struct sockaddr_in fromAddress; Boolean packetReadWasIncomplete; Boolean readResult = fRTCPInterface.handleRead(&fInBuf[fNumBytesAlreadyRead], maxPacketSize - fNumBytesAlreadyRead, numBytesRead, fromAddress, packetReadWasIncomplete); if (packetReadWasIncomplete) { fNumBytesAlreadyRead += numBytesRead; return; // more reads are needed to get the entire packet } else { // normal case: We've read the entire packet packetSize = fNumBytesAlreadyRead + numBytesRead; fNumBytesAlreadyRead = 0; // for next time } if (!readResult) break; // Ignore the packet if it was looped-back from ourself: Boolean packetWasFromOurHost = False; if (RTCPgs()->wasLoopedBackFromUs(envir(), fromAddress)) { packetWasFromOurHost = True; // However, we still want to handle incoming RTCP packets from // *other processes* on the same machine. To distinguish this // case from a true loop-back, check whether we've just sent a // packet of the same size. (This check isn't perfect, but it seems // to be the best we can do.) if (fHaveJustSentPacket && fLastPacketSentSize == packetSize) { // This is a true loop-back: fHaveJustSentPacket = False; break; // ignore this packet } } unsigned char* pkt = fInBuf; if (fIsSSMSource && !packetWasFromOurHost) { // This packet is assumed to have been received via unicast (because we're a SSM source, and SSM receivers send back RTCP "RR" // packets via unicast). 'Reflect' the packet by resending it to the multicast group, so that any other receivers can also // get to see it. // NOTE: Denial-of-service attacks are possible here. // Users of this software may wish to add their own, // application-specific mechanism for 'authenticating' the // validity of this packet before reflecting it. // NOTE: The test for "!packetWasFromOurHost" means that we won't reflect RTCP packets that come from other processes on // the same host as us. The reason for this is that the 'packet size' test above is not 100% reliable; some packets // that were truly looped back from us might not be detected as such, and this might lead to infinite forwarding/receiving // of some packets. To avoid this possibility, we only reflect RTCP packets that we know for sure originated elsewhere. // (Note, though, that if we ever re-enable the code in "Groupsock::multicastSendOnly()", then we could remove the test for // "!packetWasFromOurHost".) fRTCPInterface.sendPacket(pkt, packetSize); fHaveJustSentPacket = True; fLastPacketSentSize = packetSize; } #ifdef DEBUG fprintf(stderr, "[%p]saw incoming RTCP packet (from address %s, port %d)\n", this, AddressString(fromAddress).val(), ntohs(fromAddress.sin_port)); for (unsigned i = 0; i < packetSize; ++i) { if (i%4 == 0) fprintf(stderr, " "); fprintf(stderr, "%02x", pkt[i]); } fprintf(stderr, "\n"); #endif int totPacketSize = IP_UDP_HDR_SIZE + packetSize; // Check the RTCP packet for validity: // It must at least contain a header (4 bytes), and this header // must be version=2, with no padding bit, and a payload type of // SR (200) or RR (201): if (packetSize < 4) break; unsigned rtcpHdr = ntohl(*(u_int32_t*)pkt); if ((rtcpHdr & 0xE0FE0000) != (0x80000000 | (RTCP_PT_SR<<16))) { #ifdef DEBUG fprintf(stderr, "rejected bad RTCP packet: header 0x%08x\n", rtcpHdr); #endif break; } // Process each of the individual RTCP 'subpackets' in (what may be) // a compound RTCP packet. int typeOfPacket = PACKET_UNKNOWN_TYPE; unsigned reportSenderSSRC = 0; Boolean packetOK = False; while (1) { unsigned rc = (rtcpHdr>>24)&0x1F; unsigned pt = (rtcpHdr>>16)&0xFF; unsigned length = 4*(rtcpHdr&0xFFFF); // doesn't count hdr ADVANCE(4); // skip over the header if (length > packetSize) break; // Assume that each RTCP subpacket begins with a 4-byte SSRC: if (length < 4) break; length -= 4; reportSenderSSRC = ntohl(*(u_int32_t*)pkt); ADVANCE(4); Boolean subPacketOK = False; switch (pt) { case RTCP_PT_SR: { #ifdef DEBUG fprintf(stderr, "SR\n"); #endif if (length < 20) break; length -= 20; // Extract the NTP timestamp, and note this: unsigned NTPmsw = ntohl(*(u_int32_t*)pkt); ADVANCE(4); unsigned NTPlsw = ntohl(*(u_int32_t*)pkt); ADVANCE(4); unsigned rtpTimestamp = ntohl(*(u_int32_t*)pkt); ADVANCE(4); if (fSource != NULL) { RTPReceptionStatsDB& receptionStats = fSource->receptionStatsDB(); receptionStats.noteIncomingSR(reportSenderSSRC, NTPmsw, NTPlsw, rtpTimestamp); } ADVANCE(8); // skip over packet count, octet count // If a 'SR handler' was set, call it now: if (fSRHandlerTask != NULL) (*fSRHandlerTask)(fSRHandlerClientData); // The rest of the SR is handled like a RR (so, no "break;" here) } case RTCP_PT_RR: { #ifdef DEBUG fprintf(stderr, "RR\n"); #endif unsigned reportBlocksSize = rc*(6*4); if (length < reportBlocksSize) break; length -= reportBlocksSize; if (fSink != NULL) { // Use this information to update stats about our transmissions: RTPTransmissionStatsDB& transmissionStats = fSink->transmissionStatsDB(); for (unsigned i = 0; i < rc; ++i) { unsigned senderSSRC = ntohl(*(u_int32_t*)pkt); ADVANCE(4); // We care only about reports about our own transmission, not others' if (senderSSRC == fSink->SSRC()) { unsigned lossStats = ntohl(*(u_int32_t*)pkt); ADVANCE(4); unsigned highestReceived = ntohl(*(u_int32_t*)pkt); ADVANCE(4); unsigned jitter = ntohl(*(u_int32_t*)pkt); ADVANCE(4); unsigned timeLastSR = ntohl(*(u_int32_t*)pkt); ADVANCE(4); unsigned timeSinceLastSR = ntohl(*(u_int32_t*)pkt); ADVANCE(4); transmissionStats.noteIncomingRR(reportSenderSSRC, fromAddress, lossStats, highestReceived, jitter, timeLastSR, timeSinceLastSR); } else { ADVANCE(4*5); } } } else { ADVANCE(reportBlocksSize); } if (pt == RTCP_PT_RR) { // i.e., we didn't fall through from 'SR' // If a 'RR handler' was set, call it now: // Specific RR handler: if (fSpecificRRHandlerTable != NULL) { netAddressBits fromAddr; portNumBits fromPortNum; if (tcpReadStreamSocketNum < 0) { // Normal case: We read the RTCP packet over UDP fromAddr = fromAddress.sin_addr.s_addr; fromPortNum = ntohs(fromAddress.sin_port); } else { // Special case: We read the RTCP packet over TCP (interleaved) // Hack: Use the TCP socket and channel id to look up the handler fromAddr = tcpReadStreamSocketNum; fromPortNum = tcpReadStreamChannelId; } Port fromPort(fromPortNum); RRHandlerRecord* rrHandler = (RRHandlerRecord*)(fSpecificRRHandlerTable->Lookup(fromAddr, (~0), fromPort)); if (rrHandler != NULL) { if (rrHandler->rrHandlerTask != NULL) { (*(rrHandler->rrHandlerTask))(rrHandler->rrHandlerClientData); } } } // General RR handler: if (fRRHandlerTask != NULL) (*fRRHandlerTask)(fRRHandlerClientData); } subPacketOK = True; typeOfPacket = PACKET_RTCP_REPORT; break; } case RTCP_PT_BYE: { #ifdef DEBUG fprintf(stderr, "BYE\n"); #endif // If a 'BYE handler' was set, arrange for it to be called at the end of this routine. // (Note: We don't call it immediately, in case it happens to cause "this" to be deleted.) if (fByeHandlerTask != NULL && (!fByeHandleActiveParticipantsOnly || (fSource != NULL && fSource->receptionStatsDB().lookup(reportSenderSSRC) != NULL) || (fSink != NULL && fSink->transmissionStatsDB().lookup(reportSenderSSRC) != NULL))) { callByeHandler = True; } // We should really check for & handle >1 SSRCs being present ##### subPacketOK = True; typeOfPacket = PACKET_BYE; break; } // Later handle SDES, APP, and compound RTCP packets ##### default: #ifdef DEBUG fprintf(stderr, "UNSUPPORTED TYPE(0x%x)\n", pt); #endif subPacketOK = True; break; } if (!subPacketOK) break; // need to check for (& handle) SSRC collision! ##### #ifdef DEBUG fprintf(stderr, "validated RTCP subpacket (type %d): %d, %d, %d, 0x%08x\n", typeOfPacket, rc, pt, length, reportSenderSSRC); #endif // Skip over any remaining bytes in this subpacket: ADVANCE(length); // Check whether another RTCP 'subpacket' follows: if (packetSize == 0) { packetOK = True; break; } else if (packetSize < 4) { #ifdef DEBUG fprintf(stderr, "extraneous %d bytes at end of RTCP packet!\n", packetSize); #endif break; } rtcpHdr = ntohl(*(u_int32_t*)pkt); if ((rtcpHdr & 0xC0000000) != 0x80000000) { #ifdef DEBUG fprintf(stderr, "bad RTCP subpacket: header 0x%08x\n", rtcpHdr); #endif break; } } if (!packetOK) { #ifdef DEBUG fprintf(stderr, "rejected bad RTCP subpacket: header 0x%08x\n", rtcpHdr); #endif break; } else { #ifdef DEBUG fprintf(stderr, "validated entire RTCP packet\n"); #endif } onReceive(typeOfPacket, totPacketSize, reportSenderSSRC); // Finally, if we need to call a "BYE" handler, do so now (in case it causes "this" to get deleted): if (callByeHandler && fByeHandlerTask != NULL/*sanity check*/) { TaskFunc* byeHandler = fByeHandlerTask; fByeHandlerTask = NULL; // because we call the handler only once, by default (*byeHandler)(fByeHandlerClientData); } } while (0); }
int main(int argc, char ** argv) { int listen_port = -1; char listen_port_str[8]; const char * ctrl_socket_path = NULL; { int opt; while ((opt = getopt(argc, argv, "p:hu:")) != EOF) { switch (opt) { case 'p' : listen_port = atoi(optarg); break; case 'h' : fprintf(stderr, "%s [-p port] [-u socket-path]\n", argv[0]); fprintf(stderr, "default: -p 9134\n"); exit(0); case 'u' : ctrl_socket_path = optarg; break; } } argc -= optind; argv += optind; } if (listen_port == -1) { listen_port = 9134; } sprintf(listen_port_str, "%d", listen_port); typedef std::vector<fd_ctx> server_sockets_t; server_sockets_t server_sockets; peer_sockets_t peer_sockets; fd_ctx ctrl_socket, ctrl_socket_conn; bool ctrl_socket_mode_listen = false; bool decay_mode = false; ctrl_socket.fd = -1; ctrl_socket_conn.fd = -1; int sockets_inherited = 0; int epoll = epoll_create(1024); if (epoll < 0) { VPERROR("epoll_create"); exit(1); } if (ctrl_socket_path) { int s = socket(PF_UNIX, SOCK_SEQPACKET, 0); if (s < 0) { VPERROR("socket(AF_UNIX)"); exit(1); } struct sockaddr_un sun; sun.sun_family = AF_UNIX; strncpy(sun.sun_path, ctrl_socket_path, sizeof(sun.sun_path)); if (connect(s, (sockaddr *) &sun, sizeof(sun))) { if (errno == ECONNREFUSED || errno == ENOENT) { if (errno == ECONNREFUSED) { if (unlink(ctrl_socket_path) < 0) { fprintf(stderr, "unlink(%s): %s\n", ctrl_socket_path, strerror(errno)); exit(1); } } ctrl_socket_listen(s, ctrl_socket_path); ctrl_socket.fd = s; poll_in(epoll, &ctrl_socket); ctrl_socket_mode_listen = true; } else { fprintf(stderr, "connect(%s): %s\n", ctrl_socket_path, strerror(errno)); } } else { char buf[16]; ssize_t n = send(s, "unlisten", sizeof("unlisten") - 1, 0); if (n < 0) { VPERROR("sendmsg"); exit(1); } else if (n == 0) { fprintf(stderr, "unexpected EOF\n"); exit(1); } // blocking read n = recv(s, buf, sizeof(buf), 0); if (strncmp(buf, "unlistening", strlen("unlistening")) != 0) { fprintf(stderr, "running server reported: "); fwrite(buf, n, 1, stderr); exit(1); } ctrl_socket_conn.fd = s; poll_in(epoll, &ctrl_socket_conn); } } { struct addrinfo hints, * ai_res; hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; hints.ai_flags = AI_PASSIVE; int r = getaddrinfo(NULL, listen_port_str, &hints, &ai_res); if (r) { fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(r)); exit(1); } for (struct addrinfo * ai = ai_res; ai; ai = ai->ai_next) { int s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (s < 0) { VPERROR("socket"); exit(1); } if (ai->ai_family == AF_INET6) { int on = 1; if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&on, sizeof(on)) == -1) { VPERROR("setsockopt(IPV6_ONLY)"); exit(1); } } { int on = 1; if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on)) == -1) { VPERROR("setsockopt(REUSEADDR)"); exit(1); } } if (bind(s, ai->ai_addr, ai->ai_addrlen) < 0) { VPERROR("bind"); exit(1); } if (listen(s, 50) < 0) { VPERROR("listen"); exit(1); } fd_ctx c; c.fd = s; c.is_server = true; c.protocol = ai->ai_protocol; char * strp = c.buf; int slen = sizeof(c.buf); if (ai->ai_family == AF_INET6) { *strp++ = '['; slen -= 2; } get_ip_str(ai->ai_addr, strp, slen); if (ai->ai_family == AF_INET6) { strcat(c.buf, "]"); } sprintf(c.buf + strlen(c.buf), ":%d", listen_port); server_sockets.push_back(c); } freeaddrinfo(ai_res); } for (int i = 0; i < server_sockets.size(); ++i) { poll_in(epoll, &server_sockets[i]); } epoll_event epoll_events[32]; const int epoll_max_events = 32; fd_ctx fd_ctx_finder; signal(SIGUSR1, sigusr1); signal(SIGPIPE, SIG_IGN); total_sockets = server_sockets.size(); time_t status_time = time(NULL); while (total_sockets) { if (unlikely(got_sigusr1)) { // close listening sockets for (int i = 0; i < server_sockets.size(); ++i) { fprintf(stderr, "close server %s\n", server_sockets[i].buf); if (epoll_ctl(epoll, EPOLL_CTL_DEL, server_sockets[i].fd, NULL) < 0) { VPERROR("epoll_ctl"); } close(server_sockets[i].fd); --total_sockets; } got_sigusr1 = false; } if (unlikely(status_time + 5 < time(NULL))) { fprintf(stderr, "%d connections, %d identified peers\n", total_connections - server_sockets.size(), peer_sockets.size()); status_time = time(NULL); } int ep_num = epoll_wait(epoll, epoll_events, epoll_max_events, 1000); if (unlikely(ep_num < 0)) { if (errno == EINTR) continue; VPERROR("epoll_wait"); continue; } bool epoll_restart = false; for (int epi = 0; epi < ep_num && ! epoll_restart; ++epi) { fd_ctx * ctxp = (fd_ctx *) epoll_events[epi].data.ptr; if (unlikely(ctxp == &ctrl_socket)) { sockaddr_storage ss; socklen_t sl = sizeof(ss); int nsock = accept(ctxp->fd, (sockaddr *) &ss, &sl); if (nsock < 0) { VPERROR("accept"); continue; } epoll_event ev; ev.events = EPOLLIN; ev.data.ptr = (void *) &ctrl_socket_conn; if (epoll_ctl(epoll, EPOLL_CTL_ADD, nsock, &ev) < 0) { VPERROR("epoll_ctl"); close(nsock); continue; } // we only ever accept one ctrl client if (epoll_ctl(epoll, EPOLL_CTL_DEL, ctrl_socket.fd, NULL) < 0) { VPERROR("epoll_ctl"); close(nsock); continue; } ctrl_socket_conn.fd = nsock; } else if (unlikely(ctxp == &ctrl_socket_conn)) { if (ctrl_socket_mode_listen) { char buf[1024]; int n = read(ctxp->fd, buf, sizeof(buf)); if (n < 0) { if (errno == EINTR || errno == EAGAIN) continue; VPERROR("read"); close(ctxp->fd); poll_in(epoll, &ctrl_socket); } else if (n == 0) { close(ctxp->fd); poll_in(epoll, &ctrl_socket); } else { if (strncmp(buf, "unlisten", sizeof("unlisten") - 1) == 0) { for (int i = 0; i < server_sockets.size(); ++i) { fprintf(stderr, "close server %s\n", server_sockets[i].buf); if (epoll_ctl(epoll, EPOLL_CTL_DEL, server_sockets[i].fd, NULL) < 0) { VPERROR("epoll_ctl"); } close(server_sockets[i].fd); --total_sockets; } if (write(ctrl_socket_conn.fd, "unlistening", sizeof("unlistening") - 1) < 0) { VPERROR("write"); } else { int nsent = 0; do { nsent = send_fds(ctrl_socket_conn.fd, epoll, peer_sockets.begin(), peer_sockets.end(), &peer_sockets); if (nsent) { fprintf(stderr, "bulk send: %d\n", nsent); } } while (nsent && ! peer_sockets.empty()); epoll_restart = true; decay_mode = true; } } } } else { msghdr msg; iovec iov; optional_buf<MAX_CONTROL_MESSAGE_CONTROL_SIZE, (MAX_CONTROL_MESSAGE_TOTAL_SIZE > FDCTX_BUFFER_SIZE)> control; char * controlp = control.placeholder ? ctxp->buf + MAX_CONTROL_MESSAGE_SIZE : control.value; optional_buf<MAX_CONTROL_MESSAGE_SIZE, (MAX_CONTROL_MESSAGE_SIZE > FDCTX_BUFFER_SIZE)> buf; char * bufp = buf.placeholder ? ctxp->buf : control.value; iov.iov_base = bufp; iov.iov_len = MAX_CONTROL_MESSAGE_SIZE; msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = (void *) controlp; msg.msg_controllen = MAX_CONTROL_MESSAGE_CONTROL_SIZE; msg.msg_flags = 0; int n = recvmsg(ctxp->fd, &msg, 0); if (n < 0) { VPERROR("recvmsg"); } else if (n == 0) { fprintf(stderr, "unexpected close\n"); close(ctxp->fd); } else { if (strncmp((const char *) iov.iov_base, "desc", std::min(4, n)) == 0) { cmsghdr * cmp = CMSG_FIRSTHDR(&msg); if (cmp->cmsg_level != SOL_SOCKET || cmp->cmsg_type != SCM_RIGHTS) { fprintf(stderr, "malformed control message: wrong type\n"); exit(1); } int * uidp = (int *) ((char *) iov.iov_base + 4); int * uidpend = (int *) ((char *) iov.iov_base + n); int fd_count = 0; for (; uidp < uidpend; ++uidp, ++fd_count) { int fd = * ((int *) CMSG_DATA(cmp) + fd_count); ++sockets_inherited; ++total_sockets; fd_ctx * cp = new fd_ctx; cp->fd = fd; cp->faf_uid = *uidp; cp->is_server = false; cp->protocol = IPPROTO_TCP; cp->buf_len = 0; epoll_event ev; ev.events = EPOLLIN; ev.data.ptr = (void *) cp; if (epoll_ctl(epoll, EPOLL_CTL_ADD, cp->fd, &ev) < 0) { VPERROR("epoll_ctl"); --total_sockets; close(cp->fd); delete cp; } if (cp->faf_uid != -1) { peer_sockets.insert(cp); } } } else if (strncmp((const char *) iov.iov_base, "exit", std::min(4, n)) == 0) { close(ctxp->fd); int s = socket(PF_UNIX, SOCK_SEQPACKET, 0); if (s < 0) { VPERROR("socket(PF_UNIX)"); } else { ctrl_socket_listen(s, ctrl_socket_path); ctrl_socket.fd = s; poll_in(epoll, &ctrl_socket); ctrl_socket_mode_listen = true; } fprintf(stderr, "%d sockets inherited from the dead\n", sockets_inherited); } } } } else if (unlikely(ctxp->is_server && ctxp->protocol == IPPROTO_TCP)) { sockaddr_storage saddr; socklen_t saddrlen = sizeof(saddr); int nsock = accept(ctxp->fd, (sockaddr *) &saddr, &saddrlen); if (nsock < 0) { VPERROR("accept"); } else { ++total_sockets; fd_ctx * cp = new fd_ctx; cp->fd = nsock; cp->faf_uid = -1; cp->is_server = false; cp->protocol = IPPROTO_TCP; cp->buf_len = 0; epoll_event ev; ev.events = EPOLLIN; ev.data.ptr = (void *) cp; if (epoll_ctl(epoll, EPOLL_CTL_ADD, nsock, &ev) < 0) { VPERROR("epoll_ctl"); --total_sockets; close(nsock); delete cp; } } } else { if (unlikely(decay_mode && ctxp->buf_len == 0)) { fprintf(stderr, "single send\n"); send_fd(ctrl_socket_conn.fd, epoll, ctxp); if (ctxp->faf_uid != -1) { peer_sockets.erase(ctxp); } continue; // -> next epoll result } int n = read(ctxp->fd, ctxp->buf + ctxp->buf_len, PEER_CTX_BUF_SIZE - ctxp->buf_len); if (unlikely(n < 0)) { if (errno != ECONNRESET && errno != EAGAIN && errno != EINTR) { VPERROR("read"); } continue; } else if (unlikely(n == 0)) { close(ctxp->fd); --total_sockets; if (ctxp->faf_uid != -1) { peer_sockets.erase(ctxp); } ctxp->remove_myself_from_peer_caches(); --ctxp->refcount; if (ctxp->refcount == 0) { delete ctxp; } else { ctxp->faf_uid = -1; } } else { ctxp->buf_len += n; char * buf_head = ctxp->buf; bool postprocess = true; while (buf_head < ctxp->buf + ctxp->buf_len) { proxy_msg_header * h = (proxy_msg_header *) buf_head; const int buf_len = ctxp->buf + ctxp->buf_len - buf_head; const int in_msg_size = ntohl(h->size); if (buf_len < 4) { break; } if (unlikely(buf_len > PEER_CTX_BUF_SIZE)) { // message to big if (epoll_ctl(epoll, EPOLL_CTL_DEL, ctxp->fd, NULL) < 0) { VPERROR("epoll_ctl"); } close(ctxp->fd); --total_sockets; if (ctxp->faf_uid != -1) { peer_sockets.erase(ctxp); } ctxp->remove_myself_from_peer_caches(); --ctxp->refcount; if (ctxp->refcount == 0) { delete ctxp; } else { ctxp->faf_uid = -1; } postprocess = false; break; } if (in_msg_size + 4 > buf_len) { break; } if (unlikely(ctxp->faf_uid == -1)) { proxy_msg_header_set_uid * hu = (proxy_msg_header_set_uid *) h; ctxp->faf_uid = ntohs(hu->uid); peer_sockets.insert(ctxp); buf_head += in_msg_size + 4; continue; // -> next message from this fd_ctx } // in decay mode we always drop, because we expect our // caches and refcounts to be inconsistent // we can decay without bookkeeping if we never send any packets // out (== we never expect a context to exists unless epoll still // knows about it) if (! decay_mode) { int uid = ntohs(h->destuid); fd_ctx * peer = ctxp->peers.find(uid); if (unlikely(! peer)) { fd_ctx_finder.faf_uid = uid; peer_sockets_t::iterator iter = peer_sockets.find(&fd_ctx_finder); if (iter != peer_sockets.end()) { peer = *iter; ctxp->peers.add(peer); } else { buf_head += in_msg_size + 4; continue; } } int in_port = ntohs(h->port); proxy_msg_header_to_peer * hout = (proxy_msg_header_to_peer *) (buf_head + OUT_HEADER_OFFSET_ADJ); hout->port = htons(in_port); const int out_size = in_msg_size - OUT_HEADER_OFFSET_ADJ; hout->size = htonl(out_size); { int n = write(peer->fd, (char *) hout, out_size + 4); if (unlikely(n < 0)) { if (errno != ECONNRESET && errno != EPIPE) { VPERROR("write"); } } else if (unlikely(n != out_size + 4)) { fprintf(stderr, "short write (%d of %d\n", n, out_size + 4); } } } buf_head += in_msg_size + 4; } if (likely(postprocess)) { int new_buflen = ctxp->buf + ctxp->buf_len - buf_head; if (unlikely(new_buflen && ctxp->buf != buf_head)) { for (char * p = ctxp->buf; buf_head < ctxp->buf + ctxp->buf_len; ++p, ++buf_head) { *p = *buf_head; } } ctxp->buf_len = new_buflen; } // we want to get rid of clients as soon as possible and // dont wait for them to send the next message to trigger it if (unlikely(decay_mode && ctxp->buf_len == 0)) { send_fd(ctrl_socket_conn.fd, epoll, ctxp); if (ctxp->faf_uid != -1) { peer_sockets.erase(ctxp); } } } } } } if (decay_mode && ctrl_socket_path) { close(ctrl_socket.fd); unlink(ctrl_socket_path); if (write(ctrl_socket_conn.fd, "exit", strlen("exit")) < 0) { VPERROR("send"); } } fprintf(stderr, "exit due to %d sockets left to serve\n", total_sockets); exit(0); }
static int dhcp_get_ack(struct dhcp_context * context, int wait_ticks) { int error = 0; const struct in_addr * ip; int len; int n; struct dhcp * reply; struct in_addr server_id; struct socket * timer_arg; timer_arg = context->so; reply = dhcp_context_reply(context); timeout((timeout_fcn_t)dhcp_timeout, &timer_arg, wait_ticks); while (1) { error = receive_packet(context->so, context->reply, sizeof(context->reply), &n); if (error == 0) { dhcp_msgtype_t msg; dhcpol_t options; dprintf(("\ndhcp: received packet length %d\n", n)); if (n < (int)sizeof(struct dhcp)) { dprintf(("dhcp: packet is too short %d < %d\n", n, (int)sizeof(struct dhcp))); continue; } if (ntohl(reply->dp_xid) != context->xid || bcmp(reply->dp_chaddr, link_address(context->dl_p), link_address_length(context->dl_p)) != 0) { /* not for us */ continue; } (void)dhcpol_parse_packet(&options, reply, n); server_id.s_addr = 0; ip = (const struct in_addr *) dhcpol_find(&options, dhcptag_server_identifier_e, &len, NULL); if (ip != NULL && len >= (int)sizeof(*ip)) { server_id = *ip; } msg = get_dhcp_msgtype(&options); if (msg == dhcp_msgtype_nak_e && server_id.s_addr == context->server_id.s_addr) { /* server NAK'd us, start over */ dhcpol_free(&options); error = EPROTO; untimeout((timeout_fcn_t)dhcp_timeout, &timer_arg); break; } if (msg != dhcp_msgtype_ack_e || reply->dp_yiaddr.s_addr == 0 || reply->dp_yiaddr.s_addr == INADDR_BROADCAST) { /* ignore the packet */ goto next_packet; } printf("dhcp: received ACK: server " IP_FORMAT " IP address " IP_FORMAT "\n", IP_LIST(&server_id), IP_LIST(&reply->dp_yiaddr)); context->iaddr = reply->dp_yiaddr; ip = (const struct in_addr *) dhcpol_find(&options, dhcptag_subnet_mask_e, &len, NULL); if (ip != NULL && len >= (int)sizeof(*ip)) { context->netmask = *ip; } ip = (const struct in_addr *) dhcpol_find(&options, dhcptag_router_e, &len, NULL); if (ip != NULL && len >= (int)sizeof(*ip)) { context->router = *ip; } dhcpol_free(&options); untimeout((timeout_fcn_t)dhcp_timeout, &timer_arg); break; next_packet: dhcpol_free(&options); } else if ((error != EWOULDBLOCK)) { /* if some other error occurred, we're done */ untimeout((timeout_fcn_t)dhcp_timeout, &timer_arg); break; } else if (timer_arg == NULL) { /* timed out */ break; } else { /* wait for a wait to arrive, or a timeout to occur */ socket_lock(context->so, 1); error = sbwait(&context->so->so_rcv); socket_unlock(context->so, 1); } } return (error); }
int rc_send_server (rc_handle *rh, SEND_DATA *data, char *msg) { int sockfd; struct sockaddr_in sinlocal; struct sockaddr_in sinremote; AUTH_HDR *auth, *recv_auth; uint32_t auth_ipaddr, nas_ipaddr; char *server_name; /* Name of server to query */ socklen_t salen; int result = 0; int total_length; int length; int retry_max; size_t secretlen; char secret[MAX_SECRET_LENGTH + 1]; unsigned char vector[AUTH_VECTOR_LEN]; // uint16_t for alignment uint16_t recv_buffer[BUFFER_LEN / sizeof(uint16_t)]; uint16_t send_buffer[BUFFER_LEN / sizeof(uint16_t)]; int retries; VALUE_PAIR *vp; struct pollfd pfd; double start_time, timeout; memset(send_buffer, 0, BUFFER_LEN); server_name = data->server; if (server_name == NULL || server_name[0] == '\0') return ERROR_RC; if ((vp = rc_avpair_get(data->send_pairs, PW_SERVICE_TYPE, 0)) && \ (vp->lvalue == PW_ADMINISTRATIVE)) { strcpy(secret, MGMT_POLL_SECRET); if ((auth_ipaddr = rc_get_ipaddr(server_name)) == 0) return ERROR_RC; } else { if(data->secret != NULL) { strncpy(secret, data->secret, MAX_SECRET_LENGTH); } /* else { */ if (rc_find_server (rh, server_name, &auth_ipaddr, secret) != 0) { rc_log(LOG_ERR, "rc_send_server: unable to find server: %s", server_name); return ERROR_RC; } /*}*/ } DEBUG(LOG_ERR, "DEBUG: rc_send_server: creating socket to: %s", server_name); sockfd = socket (AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) { memset (secret, '\0', sizeof (secret)); rc_log(LOG_ERR, "rc_send_server: socket: %s", strerror(errno)); return ERROR_RC; } memset((char *)&sinlocal, '\0', sizeof(sinlocal)); sinlocal.sin_family = AF_INET; sinlocal.sin_addr.s_addr = htonl(rc_own_bind_ipaddress(rh)); sinlocal.sin_port = htons((unsigned short) 0); if (bind(sockfd, SA(&sinlocal), sizeof(sinlocal)) < 0) { close (sockfd); memset (secret, '\0', sizeof (secret)); rc_log(LOG_ERR, "rc_send_server: bind: %s: %s", server_name, strerror(errno)); return ERROR_RC; } retry_max = data->retries; /* Max. numbers to try for reply */ retries = 0; /* Init retry cnt for blocking call */ memset ((char *)&sinremote, '\0', sizeof(sinremote)); sinremote.sin_family = AF_INET; sinremote.sin_addr.s_addr = htonl (auth_ipaddr); sinremote.sin_port = htons ((unsigned short) data->svc_port); /* * Fill in NAS-IP-Address (if needed) */ if (rc_avpair_get(data->send_pairs, PW_NAS_IP_ADDRESS, 0) == NULL) { if (sinlocal.sin_addr.s_addr == htonl(INADDR_ANY)) { if (rc_get_srcaddr(SA(&sinlocal), SA(&sinremote)) != 0) { close (sockfd); memset (secret, '\0', sizeof (secret)); return ERROR_RC; } } nas_ipaddr = ntohl(sinlocal.sin_addr.s_addr); rc_avpair_add(rh, &(data->send_pairs), PW_NAS_IP_ADDRESS, &nas_ipaddr, 0, 0); } /* Build a request */ auth = (AUTH_HDR *) send_buffer; auth->code = data->code; auth->id = data->seq_nbr; if (data->code == PW_ACCOUNTING_REQUEST) { total_length = rc_pack_list(data->send_pairs, secret, auth) + AUTH_HDR_LEN; auth->length = htons ((unsigned short) total_length); memset((char *) auth->vector, 0, AUTH_VECTOR_LEN); secretlen = strlen (secret); memcpy ((char *) auth + total_length, secret, secretlen); rc_md5_calc (vector, (unsigned char *) auth, total_length + secretlen); memcpy ((char *) auth->vector, (char *) vector, AUTH_VECTOR_LEN); } else { rc_random_vector (vector); memcpy ((char *) auth->vector, (char *) vector, AUTH_VECTOR_LEN); total_length = rc_pack_list(data->send_pairs, secret, auth) + AUTH_HDR_LEN; auth->length = htons ((unsigned short) total_length); } DEBUG(LOG_ERR, "DEBUG: local %s : 0, remote %s : %u\n", inet_ntoa(sinlocal.sin_addr), inet_ntoa(sinremote.sin_addr), data->svc_port); for (;;) { sendto (sockfd, (char *) auth, (unsigned int) total_length, (int) 0, SA(&sinremote), sizeof (struct sockaddr_in)); pfd.fd = sockfd; pfd.events = POLLIN; pfd.revents = 0; start_time = rc_getctime(); for (timeout = data->timeout; timeout > 0; timeout -= rc_getctime() - start_time) { result = poll(&pfd, 1, timeout * 1000); if (result != -1 || errno != EINTR) break; } if (result == -1) { rc_log(LOG_ERR, "rc_send_server: poll: %s", strerror(errno)); memset (secret, '\0', sizeof (secret)); close (sockfd); return ERROR_RC; } if (result == 1 && (pfd.revents & POLLIN) != 0) break; /* * Timed out waiting for response. Retry "retry_max" times * before giving up. If retry_max = 0, don't retry at all. */ if (retries++ >= retry_max) { rc_log(LOG_ERR, "rc_send_server: no reply from RADIUS server %s:%u, %s", rc_ip_hostname (auth_ipaddr), data->svc_port, inet_ntoa(sinremote.sin_addr)); close (sockfd); memset (secret, '\0', sizeof (secret)); return TIMEOUT_RC; } } salen = sizeof(sinremote); length = recvfrom (sockfd, (char *) recv_buffer, (int) sizeof (recv_buffer), (int) 0, SA(&sinremote), &salen); if (length <= 0) { rc_log(LOG_ERR, "rc_send_server: recvfrom: %s:%d: %s", server_name,\ data->svc_port, strerror(errno)); close (sockfd); memset (secret, '\0', sizeof (secret)); return ERROR_RC; } recv_auth = (AUTH_HDR *)recv_buffer; if (length < AUTH_HDR_LEN || length < ntohs(recv_auth->length)) { rc_log(LOG_ERR, "rc_send_server: recvfrom: %s:%d: reply is too short", server_name, data->svc_port); close(sockfd); memset(secret, '\0', sizeof(secret)); return ERROR_RC; } result = rc_check_reply (recv_auth, BUFFER_LEN, secret, vector, data->seq_nbr); length = ntohs(recv_auth->length) - AUTH_HDR_LEN; if (length > 0) { data->receive_pairs = rc_avpair_gen(rh, NULL, recv_auth->data, length, 0); } else { data->receive_pairs = NULL; } close (sockfd); memset (secret, '\0', sizeof (secret)); if (result != OK_RC) return result; *msg = '\0'; vp = data->receive_pairs; while (vp) { if ((vp = rc_avpair_get(vp, PW_REPLY_MESSAGE, 0))) { strcat(msg, vp->strvalue); strcat(msg, "\n"); vp = vp->next; } } if ((recv_auth->code == PW_ACCESS_ACCEPT) || (recv_auth->code == PW_PASSWORD_ACK) || (recv_auth->code == PW_ACCOUNTING_RESPONSE)) { result = OK_RC; } else if ((recv_auth->code == PW_ACCESS_REJECT) || (recv_auth->code == PW_PASSWORD_REJECT)) { result = REJECT_RC; } else { result = BADRESP_RC; } return result; }
// track a tcp stream. returns the difference between this packet's // SEQ and the expected next SEQ. int IpConnTrack_track_stream(IpConnTrack *self, IpConn *conn, IpConnTcpQueue *queue, struct netpkt *pkt, int buffer_stream) { netpkt_tcp *tcp; netpkt_udp *udp; tcp_seq_t seq; char *dst, *src; int len, diff=0; do { tcp = pkt->pkt_tcp; udp = pkt->pkt_udp; src = pkt->pkt_msg; len = pkt->pkt_len; diff = 0; if( tcp ) { if( tcp_ack(tcp) ) { queue->ack = ntohl(tcp->ack_seq); } queue->win = ntohs(tcp->window); seq = ntohl(tcp->seq); if( !queue->seq_ok ) { queue->seq_syn = seq; queue->seq = seq; queue->seq_ok = 1; if( tcp_syn(tcp) ) { queue->seq++; } else { conn->conn_pkt_flags |= CONN_PKT_TCP_MISSED_SYN; } } diff = tcp_seq_diff(seq, queue->seq); if( diff > 1 ) { // ignore packets (far) in the future conn->conn_pkt_flags |= CONN_PKT_TCP_FUTURE_SEQ; break; } src += -diff; len -= -diff; if( len <= 0 ) { // ignore past packets break; } queue->seq += len; } else if( udp ) { } if( buffer_stream ) { dst = (char*)array_add(&queue->buf, len); assertb(dst); memcpy(dst, src, len); } } while(0); return diff; }
static void multi_dhcp_parse_options(struct multi_dhcp_message *msg, struct multi_dhcp_config *cfg) { u_int8_t *opt; memset(cfg, 0, sizeof(*cfg)); cfg->address.s_addr = msg->yiaddr; cfg->dhcpd_addr.s_addr = msg->siaddr; while((opt = multi_dhcp_dm_next_option(msg))) { u_int8_t *optdata = opt+2; u_int8_t optsize = *(opt+1); u_int8_t m; switch(*opt) { case DHCP_OPTION_TYPE: if (optsize == 1) cfg->dhcpmsgtype = *optdata; break; case DHCP_OPTION_SERVER: if (optsize == 4) cfg->dhcpd_addr.s_addr = multi_dhcp_get_unaligned32((u_int32_t *)optdata); break; case BOOTP_OPTION_NETMASK: if (optsize == 4) cfg->netmask.s_addr = multi_dhcp_get_unaligned32((u_int32_t *)optdata); break; case BOOTP_OPTION_GATEWAY: if (optsize >= 4) cfg->gateway.s_addr = multi_dhcp_get_unaligned32((u_int32_t *)optdata); break; case BOOTP_OPTION_DNS: if (!(optsize & 3)) { u_int8_t n; m = optsize / 4; if (m > MAXOPTS) m = MAXOPTS; cfg->dns_num = m; for (n=0; n<m; n++) cfg->dns[n].s_addr = multi_dhcp_get_unaligned32((u_int32_t *)(optdata+4*n)); } break; case BOOTP_OPTION_HOSTNAME: if (optsize >= sizeof(cfg->hostname)) optsize = sizeof(cfg->hostname)-1; memcpy(cfg->hostname, optdata, optsize); cfg->hostname[optsize] = 0; break; case BOOTP_OPTION_DOMAIN: if (optsize >= sizeof(cfg->domainname)) optsize = sizeof(cfg->domainname)-1; memcpy(cfg->domainname, optdata, optsize); cfg->domainname[optsize] = 0; break; case BOOTP_OPTION_BROADCAST: if (optsize == 4) cfg->broadcast.s_addr = multi_dhcp_get_unaligned32((u_int32_t *)optdata); break; case DHCP_OPTION_LEASE: if (optsize == 4) cfg->lease = ntohl(multi_dhcp_get_unaligned32((u_int32_t *)optdata)); break; case DHCP_OPTION_OVERLOAD: if (optsize == 1 && *optdata <= DHCP_OVERLOAD_BOTH) msg->overload = *optdata; break; case DHCP_OPTION_T1: if (optsize == 4) cfg->t1 = ntohl(multi_dhcp_get_unaligned32((u_int32_t *)optdata)); break; case DHCP_OPTION_T2: if (optsize == 4) cfg->t2 = ntohl(multi_dhcp_get_unaligned32((u_int32_t *)optdata)); break; } } }
/** * sk_run_filter - run a filter on a socket * @skb: buffer to run the filter on * @filter: filter to apply * @flen: length of filter * * Decode and apply filter instructions to the skb->data. * Return length to keep, 0 for none. skb is the data we are * filtering, filter is the array of filter instructions, and * len is the number of filter blocks in the array. */ unsigned int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int flen) { struct sock_filter *fentry; /* We walk down these */ void *ptr; u32 A = 0; /* Accumulator */ u32 X = 0; /* Index Register */ u32 mem[BPF_MEMWORDS]; /* Scratch Memory Store */ u32 tmp; int k; int pc; /* * Process array of filter instructions. */ for (pc = 0; pc < flen; pc++) { fentry = &filter[pc]; switch (fentry->code) { case BPF_ALU|BPF_ADD|BPF_X: A += X; continue; case BPF_ALU|BPF_ADD|BPF_K: A += fentry->k; continue; case BPF_ALU|BPF_SUB|BPF_X: A -= X; continue; case BPF_ALU|BPF_SUB|BPF_K: A -= fentry->k; continue; case BPF_ALU|BPF_MUL|BPF_X: A *= X; continue; case BPF_ALU|BPF_MUL|BPF_K: A *= fentry->k; continue; case BPF_ALU|BPF_DIV|BPF_X: if (X == 0) return 0; A /= X; continue; case BPF_ALU|BPF_DIV|BPF_K: A /= fentry->k; continue; case BPF_ALU|BPF_AND|BPF_X: A &= X; continue; case BPF_ALU|BPF_AND|BPF_K: A &= fentry->k; continue; case BPF_ALU|BPF_OR|BPF_X: A |= X; continue; case BPF_ALU|BPF_OR|BPF_K: A |= fentry->k; continue; case BPF_ALU|BPF_LSH|BPF_X: A <<= X; continue; case BPF_ALU|BPF_LSH|BPF_K: A <<= fentry->k; continue; case BPF_ALU|BPF_RSH|BPF_X: A >>= X; continue; case BPF_ALU|BPF_RSH|BPF_K: A >>= fentry->k; continue; case BPF_ALU|BPF_NEG: A = -A; continue; case BPF_JMP|BPF_JA: pc += fentry->k; continue; case BPF_JMP|BPF_JGT|BPF_K: pc += (A > fentry->k) ? fentry->jt : fentry->jf; continue; case BPF_JMP|BPF_JGE|BPF_K: pc += (A >= fentry->k) ? fentry->jt : fentry->jf; continue; case BPF_JMP|BPF_JEQ|BPF_K: pc += (A == fentry->k) ? fentry->jt : fentry->jf; continue; case BPF_JMP|BPF_JSET|BPF_K: pc += (A & fentry->k) ? fentry->jt : fentry->jf; continue; case BPF_JMP|BPF_JGT|BPF_X: pc += (A > X) ? fentry->jt : fentry->jf; continue; case BPF_JMP|BPF_JGE|BPF_X: pc += (A >= X) ? fentry->jt : fentry->jf; continue; case BPF_JMP|BPF_JEQ|BPF_X: pc += (A == X) ? fentry->jt : fentry->jf; continue; case BPF_JMP|BPF_JSET|BPF_X: pc += (A & X) ? fentry->jt : fentry->jf; continue; case BPF_LD|BPF_W|BPF_ABS: k = fentry->k; load_w: ptr = load_pointer(skb, k, 4, &tmp); if (ptr != NULL) { A = ntohl(get_unaligned((__be32 *)ptr)); continue; } break; case BPF_LD|BPF_H|BPF_ABS: k = fentry->k; load_h: ptr = load_pointer(skb, k, 2, &tmp); if (ptr != NULL) { A = ntohs(get_unaligned((__be16 *)ptr)); continue; } break; case BPF_LD|BPF_B|BPF_ABS: k = fentry->k; load_b: ptr = load_pointer(skb, k, 1, &tmp); if (ptr != NULL) { A = *(u8 *)ptr; continue; } break; case BPF_LD|BPF_W|BPF_LEN: A = skb->len; continue; case BPF_LDX|BPF_W|BPF_LEN: X = skb->len; continue; case BPF_LD|BPF_W|BPF_IND: k = X + fentry->k; goto load_w; case BPF_LD|BPF_H|BPF_IND: k = X + fentry->k; goto load_h; case BPF_LD|BPF_B|BPF_IND: k = X + fentry->k; goto load_b; case BPF_LDX|BPF_B|BPF_MSH: ptr = load_pointer(skb, fentry->k, 1, &tmp); if (ptr != NULL) { X = (*(u8 *)ptr & 0xf) << 2; continue; } return 0; case BPF_LD|BPF_IMM: A = fentry->k; continue; case BPF_LDX|BPF_IMM: X = fentry->k; continue; case BPF_LD|BPF_MEM: A = mem[fentry->k]; continue; case BPF_LDX|BPF_MEM: X = mem[fentry->k]; continue; case BPF_MISC|BPF_TAX: X = A; continue; case BPF_MISC|BPF_TXA: A = X; continue; case BPF_RET|BPF_K: return fentry->k; case BPF_RET|BPF_A: return A; case BPF_ST: mem[fentry->k] = A; continue; case BPF_STX: mem[fentry->k] = X; continue; default: WARN_ON(1); return 0; } /* * Handle ancillary data, which are impossible * (or very difficult) to get parsing packet contents. */ switch (k-SKF_AD_OFF) { case SKF_AD_PROTOCOL: A = ntohs(skb->protocol); continue; case SKF_AD_PKTTYPE: A = skb->pkt_type; continue; case SKF_AD_IFINDEX: A = skb->dev->ifindex; continue; default: return 0; } } return 0; }
static int _parse_sockaddr(struct acl_entry *entry, grecs_value_t *value) { struct dicod_sockaddr *sptr; const char *string; if (value->type != GRECS_TYPE_STRING) { grecs_error(&entry->locus, 0, _("expected string but found list")); return 1; } string = value->v.string; if (string[0] == '/') { size_t len; struct sockaddr_un *s_un; len = strlen (string); if (len >= sizeof(s_un->sun_path)) { grecs_error(&entry->locus, 0, _("socket name too long: `%s'"), string); return 1; } sptr = create_acl_sockaddr(AF_UNIX, sizeof(s_un)); s_un = (struct sockaddr_un *) &sptr->sa; memcpy(s_un->sun_path, string, len); s_un->sun_path[len] = 0; } else { struct in_addr addr; struct sockaddr_in *s_in; char *p = strchr(string, '/'); if (p) *p = 0; if (inet_aton(string, &addr) == 0) { struct hostent *hp = gethostbyname(string); if (!hp) { grecs_error(&entry->locus, 0, _("cannot resolve host name: `%s'"), string); if (p) *p = '/'; return 1; } memcpy(&addr.s_addr, hp->h_addr, sizeof(addr.s_addr)); } addr.s_addr = ntohl(addr.s_addr); sptr = create_acl_sockaddr(AF_INET, sizeof(s_in)); s_in = (struct sockaddr_in *) &sptr->sa; s_in->sin_addr = addr; if (p) { *p++ = '/'; char *q; unsigned netlen; netlen = strtoul(p, &q, 10); if (*q == 0) { if (netlen == 0) sptr->netmask = 0; else { sptr->netmask = 0xfffffffful >> (32 - netlen); sptr->netmask <<= (32 - netlen); } } else if (*q == '.') { struct in_addr addr; if (inet_aton(p, &addr) == 0) { grecs_error(&entry->locus, 0, _("invalid netmask: `%s'"), p); return 1; } sptr->netmask = addr.s_addr; } else { grecs_error(&entry->locus, 0, _("invalid netmask: `%s'"), p); return 1; } } else
FlowSource_t *AddDynamicSource(FlowSource_t **FlowSource, struct sockaddr_storage *ss) { FlowSource_t **source; void *ptr; char *s, ident[100], path[MAXPATHLEN]; int err; union { struct sockaddr_storage *ss; struct sockaddr *sa; struct sockaddr_in *sa_in; struct sockaddr_in6 *sa_in6; } u; u.ss = ss; if ( !DynamicSourcesDir ) return NULL; source = FlowSource; while ( *source ) { source = &((*source)->next); } *source = (FlowSource_t *)calloc(1, sizeof(FlowSource_t)); if ( !*source ) { LogError("malloc() error in %s line %d: %s\n", __FILE__, __LINE__, strerror(errno) ); return NULL; } (*source)->next = NULL; (*source)->bookkeeper = NULL; (*source)->any_source = 0; (*source)->exporter_data = NULL; (*source)->xstat = NULL; (*FlowSource)->exporter_count = 0; switch (ss->ss_family) { case PF_INET: { #ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN if (ss->ss_len != sizeof(struct sockaddr_in) ) { // malformed struct LogError("Malformed IPv4 socket struct in '%s', line '%d'", __FILE__, __LINE__ ); free(*source); *source = NULL; return NULL; } #endif (*source)->sa_family = PF_INET; (*source)->ip.v6[0] = 0; (*source)->ip.v6[1] = 0; (*source)->ip.v4 = ntohl(u.sa_in->sin_addr.s_addr); ptr = &u.sa_in->sin_addr; } break; case PF_INET6: { uint64_t *ip_ptr = (uint64_t *)u.sa_in6->sin6_addr.s6_addr; #ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN if (ss->ss_len != sizeof(struct sockaddr_in6) ) { // malformed struct LogError("Malformed IPv6 socket struct in '%s', line '%d'", __FILE__, __LINE__ ); free(*source); *source = NULL; return NULL; } #endif // ptr = &((struct sockaddr_in6 *)sa)->sin6_addr; (*source)->sa_family = PF_INET6; (*source)->ip.v6[0] = ntohll(ip_ptr[0]); (*source)->ip.v6[1] = ntohll(ip_ptr[1]); ptr = &u.sa_in6->sin6_addr; } break; default: // keep compiler happy (*source)->ip.v6[0] = 0; (*source)->ip.v6[1] = 0; ptr = NULL; LogError("Unknown sa fanily: %d in '%s', line '%d'", ss->ss_family, __FILE__, __LINE__ ); free(*source); *source = NULL; return NULL; } if ( !ptr ) { free(*source); *source = NULL; return NULL; } inet_ntop(ss->ss_family, ptr, ident, sizeof(ident)); ident[99] = '\0'; dbg_printf("Dynamic Flow Source IP: %s\n", ident); if ( strchr(ident, ':') ) { // condense IPv6 addresses condense_v6(ident); } s = ident; while ( *s != '\0' ) { if ( *s == '.' || *s == ':' ) *s = '-'; s++; } dbg_printf("Dynamic Flow Source ident: %s\n", ident); strncpy((*source)->Ident, ident, IDENTLEN-1 ); (*source)->Ident[IDENTLEN-1] = '\0'; snprintf(path, MAXPATHLEN-1, "%s/%s", DynamicSourcesDir, ident); path[MAXPATHLEN-1] = '\0'; err = mkdir(path, 0755); if ( err != 0 && errno != EEXIST ) { LogError("mkdir() error in %s line %d: %s\n", __FILE__, __LINE__, strerror(errno) ); free(*source); *source = NULL; return NULL; } (*source)->datadir = strdup(path); if ( snprintf(path, MAXPATHLEN-1, "%s/%s.%lu", (*source)->datadir, NF_DUMPFILE, (unsigned long)getpid() ) >= (MAXPATHLEN-1)) { fprintf(stderr, "Path too long: %s\n", path); free(*source); *source = NULL; return NULL; } (*source)->current = strdup(path); LogInfo("Dynamically add source ident: %s in directory: %s", ident, path); return *source; } // End of AddDynamicSource
int rpki_validate_prefix(struct peer* peer, struct attr* attr, struct prefix *prefix) { struct assegment* as_segment; as_t as_number = 0; struct ip_addr ip_addr_prefix; enum pfxv_state result; char buf[BUFSIZ]; const char* prefix_string; if (!rpki_is_synchronized() || bgp_flag_check(peer->bgp, BGP_FLAG_VALIDATE_DISABLE)) { return 0; } // No aspath means route comes from iBGP if (!attr->aspath || !attr->aspath->segments) { // Set own as number as_number = peer->bgp->as; } else { as_segment = attr->aspath->segments; // Find last AsSegment while (as_segment->next) { as_segment = as_segment->next; } if (as_segment->type == AS_SEQUENCE) { // Get rightmost asn as_number = as_segment->as[as_segment->length - 1]; } else if (as_segment->type == AS_CONFED_SEQUENCE || as_segment->type == AS_CONFED_SET) { // Set own as number as_number = peer->bgp->as; } else { // RFC says: "Take distinguished value NONE as asn" // which means state is unknown return RPKI_NOTFOUND; } } // Get the prefix in requested format switch (prefix->family) { case AF_INET: ip_addr_prefix.ver = IPV4; ip_addr_prefix.u.addr4.addr = ntohl(prefix->u.prefix4.s_addr); break; #ifdef HAVE_IPV6 case AF_INET6: ip_addr_prefix.ver = IPV6; ipv6_addr_to_host_byte_order(prefix->u.prefix6.s6_addr32, ip_addr_prefix.u.addr6.addr); break; #endif /* HAVE_IPV6 */ default: return 0; } // Do the actual validation rtr_mgr_validate(rtr_config, as_number, &ip_addr_prefix, prefix->prefixlen, &result); // Print Debug output prefix_string = inet_ntop(prefix->family, &prefix->u.prefix, buf, BUFSIZ); switch (result) { case BGP_PFXV_STATE_VALID: RPKI_DEBUG("Validating Prefix %s/%hu from asn %u Result: VALID", prefix_string, prefix->prefixlen, as_number) ; return RPKI_VALID; case BGP_PFXV_STATE_NOT_FOUND: RPKI_DEBUG("Validating Prefix %s/%hu from asn %u Result: NOT FOUND", prefix_string, prefix->prefixlen, as_number) ; return RPKI_NOTFOUND; case BGP_PFXV_STATE_INVALID: RPKI_DEBUG("Validating Prefix %s/%hu from asn %u Result: INVALID", prefix_string, prefix->prefixlen, as_number) ; return RPKI_INVALID; default: RPKI_DEBUG( "Validating Prefix %s/%hu from asn %u Result: CANNOT VALIDATE", prefix_string, prefix->prefixlen, as_number) ; break; } return 0; }
int AddFlowSource(FlowSource_t **FlowSource, char *ident) { FlowSource_t **source; struct stat fstat; char *p, *q, s[MAXPATHLEN]; int has_any_source = 0; int ok; if ( DynamicSourcesDir ) return 0; source = FlowSource; while ( *source ) { has_any_source |= (*source)->any_source; source = &((*source)->next); } if ( has_any_source ) { fprintf(stderr, "Ambiguous idents not allowed\n"); return 0; } *source = (FlowSource_t *)calloc(1, sizeof(FlowSource_t)); if ( !*source ) { LogError("malloc() error in %s line %d: %s\n", __FILE__, __LINE__, strerror(errno) ); return 0; } (*source)->next = NULL; (*source)->bookkeeper = NULL; (*source)->any_source = 0; (*source)->exporter_data = NULL; (*source)->xstat = NULL; (*FlowSource)->exporter_count = 0; // separate IP address from ident if ( ( p = strchr(ident, ',')) == NULL ) { fprintf(stderr, "Syntax error for netflow source definition. Expect -n ident,IP,path\n"); return 0; } *p++ = '\0'; // separate path from IP if ( ( q = strchr(p, ',')) == NULL ) { fprintf(stderr, "Syntax error for netflow source definition. Expect -n ident,IP,path\n"); return 0; } *q++ = '\0'; if ( strchr(p, ':') != NULL ) { uint64_t _ip[2]; ok = inet_pton(PF_INET6, p, _ip); (*source)->sa_family = PF_INET6; (*source)->ip.v6[0] = ntohll(_ip[0]); (*source)->ip.v6[1] = ntohll(_ip[1]); } else { uint32_t _ip; ok = inet_pton(PF_INET, p, &_ip); (*source)->sa_family = PF_INET; (*source)->ip.v6[0] = 0; (*source)->ip.v6[1] = 0; (*source)->ip.v4 = ntohl(_ip); } switch (ok) { case 0: fprintf(stderr, "Unparsable IP address: %s\n", p); return 0; case 1: // success break; case -1: fprintf(stderr, "Error while parsing IP address: %s\n", strerror(errno)); return 0; break; } // fill in ident if ( strlen(ident) >= IDENTLEN ) { fprintf(stderr, "Source identifier too long: %s\n", ident); return 0; } if ( strchr(ident, ' ') ) { fprintf(stderr,"Illegal characters in ident %s\n", ident); exit(255); } strncpy((*source)->Ident, ident, IDENTLEN-1 ); (*source)->Ident[IDENTLEN-1] = '\0'; if ( strlen(q) >= MAXPATHLEN ) { fprintf(stderr,"Path too long: %s\n", q); exit(255); } // check for existing path if ( stat(q, &fstat) ) { fprintf(stderr, "stat() error %s: %s\n", q, strerror(errno)); return 0; } if ( !(fstat.st_mode & S_IFDIR) ) { fprintf(stderr, "No such directory: %s\n", q); return 0; } // remember path (*source)->datadir = strdup(q); if ( !(*source)->datadir ) { fprintf(stderr, "strdup() error: %s\n", strerror(errno)); return 0; } // cache current collector file if ( snprintf(s, MAXPATHLEN-1, "%s/%s.%lu", (*source)->datadir , NF_DUMPFILE, (unsigned long)getpid() ) >= (MAXPATHLEN-1)) { fprintf(stderr, "Path too long: %s\n", q); return 0; } (*source)->current = strdup(s); if ( !(*source)->current ) { fprintf(stderr, "strdup() error: %s\n", strerror(errno)); return 0; } return 1; } // End of AddFlowSource
GIT_INLINE(uint64_t) decode64(void *b) { uint32_t *p = b; return (((uint64_t)ntohl(p[0])) << 32) | ntohl(p[1]); }
GIT_INLINE(uint32_t) decode32(void *b) { return ntohl(*((uint32_t *)b)); }
void Socket::socketThread() { Json::Reader reader; bool running = true; int addrinfo_status, connect_status, socket_status = 0; while ( running ) { if ( !socketfd || socket_status ) { struct addrinfo host_info; struct addrinfo *host_info_list; // Close the existing socket, if it has been left open. if ( socketfd ) { close( socketfd ); socketfd = NULL; } // Establish connection memset( &host_info, 0, sizeof host_info ); host_info.ai_family = AF_UNSPEC; host_info.ai_socktype = SOCK_STREAM; addrinfo_status = getaddrinfo( hostname, port, &host_info, &host_info_list ); if ( addrinfo_status ) { std::cout << "couldn't get address" << std::endl ; sleep(1); continue; } socketfd = socket( host_info_list->ai_family, host_info_list->ai_socktype, host_info_list->ai_protocol ); if ( socketfd == -1 ) { socket_status = -1; std::cout << "socket error" << std::endl ; sleep(1); continue; } connect_status = connect( socketfd, host_info_list->ai_addr, host_info_list->ai_addrlen ); if ( connect_status ) { socket_status = -1; std::cout << "connect error" << std::endl ; sleep(1); continue; } socket_status = 0; } int max_message_size = 1000000; ssize_t bytes_recieved; struct hss_header header; string buffer; bytes_recieved = recv( socketfd, &header, sizeof header, 0 ); //std::cout << "received " << bytes_recieved << std::endl; if ( bytes_recieved == sizeof header ) { // Parse the header ( what there is of it ) header.string_bytes = ntohl( header.string_bytes ); if ( header.string_bytes > max_message_size ) { // Bad header, f**k it. socket_status = -3; std::cout << "bad header, disconnecting"; continue; } buffer.resize( header.string_bytes ); size_t b = recv( socketfd, (void * ) buffer.c_str(), header.string_bytes, MSG_WAITALL ); if ( b != header.string_bytes ) { } Json::Value msg; //std::cout << buffer << std::endl; reader.parse( buffer, msg ); Json::Value set = msg["set"]; if ( set.isObject() ) { Json::Value set = msg["set"]; for ( Json::ValueIterator i = set.begin(); i != set.end(); i ++ ) { string k = (string) i.memberName(); horten->set( set[k], k, flags ); } } } else if (bytes_recieved == 0) { std::cout << "host shut down." << std::endl ; socket_status = -3; sleep(1); } else if (bytes_recieved == -1 ) { std::cout << "receive error! " << errno << std::endl ; socket_status = -4; sleep(1); } } }
static void dcs_read_cb(u32 data) { pr_info("%s: data=0x%x\n", __func__, ntohl(data)); }
int IpConnTrack_track_state(IpConnTrack *self, IpConn *conn, struct netpkt *pkt) { netpkt_tcp *tcp = pkt->pkt_tcp; IpConnStats *st=0; if( conn->conn_pkt_flags & CONN_PKT_FROM_CLIENT ) { st = &conn->conn_stats_client; if( conn->conn_flags & CONN_LOCAL_CLIENT ) { conn->conn_pkt_flags |= CONN_PKT_LOCAL_SRC; } if( conn->conn_flags & CONN_LOCAL_SERVER ) { conn->conn_pkt_flags |= CONN_PKT_LOCAL_DST; } } else if( conn->conn_pkt_flags & CONN_PKT_FROM_SERVER ) { st = &conn->conn_stats_server; if( conn->conn_flags & CONN_LOCAL_CLIENT ) { conn->conn_pkt_flags |= CONN_PKT_LOCAL_DST; } if( conn->conn_flags & CONN_LOCAL_SERVER ) { conn->conn_pkt_flags |= CONN_PKT_LOCAL_SRC; } } if( st ) { st->packets++; st->bytes += pkt->pkt_len; // track the next expected sequence numbers to mark duplicate // packets. I won't complain if retries are different. pkt->pkt_tcp_seq_diff = 0; if( tcp ) { u32 seq; seq = ntohl(tcp->seq); if( !st->tcp_seq_next_ok || seq == st->tcp_seq_next ) { if( tcp_syn(tcp) ) { st->tcp_seq_next = seq + 1; } else { st->tcp_seq_next = seq + pkt->pkt_len; } st->tcp_seq_next_ok = 1; } else { pkt->pkt_tcp_seq_diff = tcp_seq_diff(seq, st->tcp_seq_next); } } } conn->conn_time_prev = conn->conn_time_last; conn->conn_time_last = mstime(); if( tcp ) { if( tcp_fin(tcp) || tcp_rst(tcp) ) { conn->conn_state = CONN_STATE_FIN; } } return 0; }
static int lcb_parse_single_with_specialized_callbacks(lcb_server_t *c, hrtime_t stop) { protocol_binary_request_header req; protocol_binary_response_header header; lcb_size_t nr; char *packet; lcb_size_t packetsize; struct lcb_command_data_st ct; lcb_connection_t conn = &c->connection; if (lcb_ringbuffer_ensure_alignment(&conn->input.buffer->ringbuffer) != 0) { lcb_error_handler(c->instance, LCB_EINTERNAL, NULL); return -1; } nr = lcb_ringbuffer_peek(&conn->input.buffer->ringbuffer, header.bytes, sizeof(header)); if (nr < sizeof(header)) { return 0; } packetsize = ntohl(header.response.bodylen) + (lcb_uint32_t)sizeof(header); if (conn->input.buffer->ringbuffer.nbytes < packetsize) { return 0; } /* Is it already timed out? */ nr = lcb_ringbuffer_peek(&c->cmd_log, req.bytes, sizeof(req)); if (nr < sizeof(req) || /* the command log doesn't know about it */ (header.response.opaque < req.request.opaque && header.response.opaque > 0)) { /* sasl comes with zero opaque */ /* already processed. */ lcb_ringbuffer_consumed(&conn->input.buffer->ringbuffer, packetsize); return 1; } packet = conn->input.buffer->ringbuffer.read_head; /* we have everything! */ if (!lcb_ringbuffer_is_continous(&conn->input.buffer->ringbuffer, LCB_RINGBUFFER_READ, packetsize)) { /* The buffer isn't continous.. for now just copy it out and ** operate on the copy ;) */ if ((packet = malloc(packetsize)) == NULL) { lcb_error_handler(c->instance, LCB_CLIENT_ENOMEM, NULL); return -1; } nr = lcb_ringbuffer_read(&conn->input.buffer->ringbuffer, packet, packetsize); if (nr != packetsize) { lcb_error_handler(c->instance, LCB_EINTERNAL, NULL); free(packet); return -1; } } nr = lcb_ringbuffer_peek(&c->output_cookies, &ct, sizeof(ct)); if (nr != sizeof(ct)) { lcb_error_handler(c->instance, LCB_EINTERNAL, NULL); if (packet != conn->input.buffer->ringbuffer.read_head) { free(packet); } return -1; } ct.vbucket = ntohs(req.request.vbucket); switch (header.response.magic) { case PROTOCOL_BINARY_REQ: /* * The only way to get request packets is if someone started * to send us TAP requests, and we don't support that anymore */ lcb_error_handler(c->instance, LCB_EINTERNAL, "Protocol error. someone sent us a command!"); return -1; case PROTOCOL_BINARY_RES: { int was_connected = c->connection_ready; if (lcb_server_purge_implicit_responses(c, header.response.opaque, stop, 0) != 0) { if (packet != conn->input.buffer->ringbuffer.read_head) { free(packet); } return -1; } if (c->instance->histogram) { lcb_record_metrics(c->instance, stop - ct.start, header.response.opcode); } if (ntohs(header.response.status) != PROTOCOL_BINARY_RESPONSE_NOT_MY_VBUCKET || header.response.opcode == CMD_GET_REPLICA || header.response.opcode == CMD_OBSERVE) { if (lcb_dispatch_response(c, &ct, (void *)packet) == -1) { /* * Internal error.. we received an unsupported response * id. This should _ONLY_ happen at development time because * we won't receive response packets with other opcodes * than we send. Let's abort here to make it easy for * the developer to know what happened.. */ lcb_error_handler(c->instance, LCB_EINTERNAL, "Received unknown command response"); abort(); return -1; } /* keep command and cookie until we get complete STAT response */ swallow_command(c, &header, was_connected); } else { int rv = handle_not_my_vbucket(c, &req, &ct); if (rv == -1) { return -1; } else if (rv == 0) { lcb_dispatch_response(c, &ct, (void *)packet); swallow_command(c, &header, was_connected); } } break; } default: lcb_error_handler(c->instance, LCB_PROTOCOL_ERROR, NULL); if (packet != conn->input.buffer->ringbuffer.read_head) { free(packet); } return -1; } if (packet != conn->input.buffer->ringbuffer.read_head) { free(packet); } else { lcb_ringbuffer_consumed(&conn->input.buffer->ringbuffer, packetsize); } return 1; }
int __loadctype(const char *name) { FILE *fp; char id[sizeof(_CTYPE_ID) - 1]; u_int32_t i, len; unsigned short *new_ctype = NULL; unsigned char *new_toupper = NULL, *new_tolower = NULL; _DIAGASSERT(name != NULL); if ((fp = fopen(name, "r")) == NULL) return 0; if (fread(id, sizeof(id), 1, fp) != 1) goto bad; if (memcmp(id, _CTYPE_ID, sizeof(id)) != 0) goto bad; if (fread(&i, sizeof(u_int32_t), 1, fp) != 1) goto bad; if ((i = ntohl(i)) != _CTYPE_REV) goto bad; if (fread(&len, sizeof(u_int32_t), 1, fp) != 1) goto bad; if ((len = ntohl(len)) != _CTYPE_NUM_CHARS) goto bad; if ((new_ctype = malloc(sizeof(UINT16) * (1 + len))) == NULL) goto bad; new_ctype[0] = 0; if (fread(&new_ctype[1], sizeof(UINT16), len, fp) != len) goto bad; if ((new_toupper = malloc(sizeof(UINT8) * (1 + len))) == NULL) goto bad; new_toupper[0] = (UINT8)EOF; if (fread(&new_toupper[1], sizeof(UINT8), len, fp) != len) goto bad; if ((new_tolower = malloc(sizeof(UINT8) * (1 + len))) == NULL) goto bad; new_tolower[0] = (UINT8)EOF; if (fread(&new_tolower[1], sizeof(UINT8), len, fp) != len) goto bad; #if BYTE_ORDER == LITTLE_ENDIAN for (i = 1; i <= len; i++) { new_ctype[i] = ntohs(new_ctype[i]); } #endif (void) fclose(fp); if (_cClass != _C_CharClassTable) free(__UNCONST(_cClass)); _cClass = new_ctype; if (_uConvT != _C_ToUpperTable) free(__UNCONST(_uConvT)); _uConvT = new_toupper; if (_lConvT != _C_ToLowerTable) free(__UNCONST(_lConvT)); _lConvT = new_tolower; return 1; bad: free(new_tolower); free(new_toupper); free(new_ctype); (void) fclose(fp); return 0; }
static int lcb_parse_single_with_packet_forward(lcb_server_t *c, hrtime_t stop) { protocol_binary_request_header req; protocol_binary_response_header header; lcb_size_t nr; lcb_size_t avail; int was_connected = c->connection_ready; uint16_t status; lcb_size_t packetsize; struct lcb_command_data_st ct; lcb_connection_t conn = &c->connection; lcb_t instance = c->instance; /* Check if we have the entire packet */ nr = lcb_ringbuffer_peek(&conn->input.buffer->ringbuffer, header.bytes, sizeof(header)); if (nr < sizeof(header)) { return 0; } packetsize = ntohl(header.response.bodylen) + (lcb_uint32_t)sizeof(header); avail = lcb_ringbuffer_get_nbytes(&conn->input.buffer->ringbuffer); if (avail < packetsize) { /* We need more data! */ return 0; } /* Is it already timed out? */ nr = lcb_ringbuffer_peek(&c->cmd_log, req.bytes, sizeof(req)); if (nr < sizeof(req) || /* the command log doesn't know about it */ (header.response.opaque < req.request.opaque && header.response.opaque > 0)) { /* sasl comes with zero opaque */ /* already processed. */ lcb_ringbuffer_consumed(&conn->input.buffer->ringbuffer, packetsize); return 1; } /* We've got the entire packet!! */ assert(header.response.magic == PROTOCOL_BINARY_RES); nr = lcb_ringbuffer_peek(&c->output_cookies, &ct, sizeof(ct)); if (nr != sizeof(ct)) { lcb_error_handler(c->instance, LCB_EINTERNAL, NULL); return -1; } ct.vbucket = ntohs(req.request.vbucket); if (lcb_server_purge_implicit_responses(c, header.response.opaque, stop, 0)) { return -1; } if (c->instance->histogram) { lcb_record_metrics(c->instance, stop - ct.start, header.response.opcode); } status = ntohs(header.response.status); if (status != PROTOCOL_BINARY_RESPONSE_NOT_MY_VBUCKET || header.response.opcode == CMD_GET_REPLICA || header.response.opcode == CMD_OBSERVE) { /* Prepare the callback data */ lcb_packet_fwd_resp_t resp; lcb_error_t err = LCB_SUCCESS; resp.version = 0; resp.v.v0.buffer = conn->input.buffer; lcb_ringbuffer_get_iov(&resp.v.v0.buffer->ringbuffer, LCB_RINGBUFFER_READ, resp.v.v0.iov); /* The IOV should only contain the exact bits for the packet */ if (resp.v.v0.iov[0].iov_len > packetsize) { resp.v.v0.iov[0].iov_len = packetsize; resp.v.v0.iov[1].iov_len = 0; } else { resp.v.v0.iov[1].iov_len = packetsize - resp.v.v0.iov[0].iov_len; } /* fire the callback */ conn->input.locked |= instance->callbacks.packet_fwd(instance, ct.cookie, err, &resp); lcb_ringbuffer_consumed(&conn->input.buffer->ringbuffer, packetsize); /* keep command and cookie until we get complete STAT response */ swallow_command(c, &header, was_connected); } else { int rv = handle_not_my_vbucket(c, &req, &ct); if (rv == -1) { return -1; } else if (rv == 0) { /* Prepare the callback data */ lcb_packet_fwd_resp_t resp; lcb_error_t err = LCB_SUCCESS; resp.version = 0; resp.v.v0.buffer = conn->input.buffer; lcb_ringbuffer_get_iov(&resp.v.v0.buffer->ringbuffer, LCB_RINGBUFFER_READ, resp.v.v0.iov); /* The IOV should only contain the exact bits for the packet */ if (resp.v.v0.iov[0].iov_len > packetsize) { resp.v.v0.iov[0].iov_len = packetsize; resp.v.v0.iov[1].iov_len = 0; } else { resp.v.v0.iov[1].iov_len = packetsize - resp.v.v0.iov[0].iov_len; } /* fire the callback */ conn->input.locked |= instance->callbacks.packet_fwd(instance, ct.cookie, err, &resp); lcb_ringbuffer_consumed(&conn->input.buffer->ringbuffer, packetsize); /* keep command and cookie until we get complete STAT response */ swallow_command(c, &header, was_connected); } } return 1; }
void multi_dhcp_parse_dhcp_msg(struct multi_dhcp_info *di, struct multi_dhcp_message *dm, struct multi_link_info *li){ struct multi_dhcp_config cfg; uint32_t t_now, t_diff; uint8_t ipaddr[INET_ADDRSTRLEN]; uint8_t baddr[INET_ADDRSTRLEN]; uint8_t gwaddr[INET_ADDRSTRLEN]; uint8_t netmask[INET_ADDRSTRLEN]; multi_dhcp_parse_options(dm, &cfg); if (dm->xid != di->xid || dm->hlen != 6 || memcmp(dm->chaddr, &(di->mac_addr),6)){ //fprintf(stderr, "Message intended for someone else!\n"); return; } switch(di->state){ case SELECTING: //One typical scenario here is if the lease expires before the //DHCP ACK for final REBIND is received if(cfg.dhcpmsgtype != DHCP_TYPE_OFFER){ MULTI_DEBUG_PRINT(stderr,"Mismatch state. In INIT but did not " "get OFFER. Got %u\n", cfg.dhcpmsgtype); return; } /* Move on to the next state, retrans count must be reset */ di->retrans_count = 0; MULTI_DEBUG_PRINT(stderr,"Received DHCP OFFER on interface %s " "(iface idx %u), will send DHCP REQUEST\n", li->dev_name, li->ifi_idx); di->cfg = cfg; di->state = REQUESTING; multi_dhcp_create_dhcp_msg(di); break; case RENEWING: case REBINDING: case REQUESTING: case REBOOTING: /* All these states */ if(cfg.dhcpmsgtype == DHCP_TYPE_NAK){ /* According to the RFC, a NAK involves moving straight back to * INIT and resending request. Moving to INIT implies resetting * variables and state, just in case */ MULTI_DEBUG_PRINT(stderr,"Got NAK in state %u. Resetting and " "retrying DISCOVER! (iface idx %u)\n", di->state, di->ifidx); di->state = INIT; di->req_sent_time = 0; //Since next packet is sent immideatly, this can 0 (as opposed //to -1 for ACK) di->retrans_count = 0; /* Set state as waiting. I can here if a) rebooting fails b) * requesting fails c) renewing fails d) rebinding fails. In the * last two, the link can be in UP state */ g_static_rw_lock_writer_lock(&(li->state_lock)); li->state = WAITING_FOR_DHCP; g_static_rw_lock_writer_unlock(&(li->state_lock)); multi_dhcp_create_dhcp_msg(di); } else if(cfg.dhcpmsgtype == DHCP_TYPE_ACK){ //Always decline DHCP address di->cfg = cfg; //Just in case, I know these are the good values di->state = BOUND; inet_ntop(AF_INET, &(cfg.address), (char*) ipaddr, INET_ADDRSTRLEN); inet_ntop(AF_INET, &(cfg.broadcast), (char*) baddr, INET_ADDRSTRLEN); inet_ntop(AF_INET, &(cfg.gateway), (char*) gwaddr, INET_ADDRSTRLEN); inet_ntop(AF_INET, &(cfg.netmask), (char*) netmask, INET_ADDRSTRLEN); //Do the timeout calculation. Be warned that inet_ntoa is NOT //reentrant. In other words, the IP adresses are wrong! MULTI_DEBUG_PRINT(stderr,"Got DHCP ACK on interface %s " "(iface idx %u). %s will be bound to IP: %s Broadcast: " "%s Gateway: %s Netmask %s (%u) Lease: %u T1: %u T2: " "%u\n", li->dev_name, li->ifi_idx, li->dev_name, ipaddr, baddr, gwaddr, netmask, 32 - (ffs(ntohl(cfg.netmask.s_addr)) - 1), cfg.lease, cfg.t1, cfg.t2); //TODO: I need some variable or check to prevent adding the same IP twice. Compare cfg is maybe sufficient? Or at least address? //pthread_mutex_lock(&(li->link_state_lock)); g_static_rw_lock_writer_lock(&(li->state_lock)); /* This is needed if one interface switches network. Otherwise, * the main thread will not know that it has to clean up (it * will just see a new set of addresses)! */ /* Need to wireless access points in order to test this, with * different subnets */ if(li->cfg.address.s_addr != 0 && (li->cfg.address.s_addr != cfg.address.s_addr || li->cfg.broadcast.s_addr != cfg.broadcast.s_addr || li->cfg.gateway.s_addr != cfg.gateway.s_addr || li->cfg.netmask.s_addr != cfg.netmask.s_addr)){ li->state = DHCP_IP_CHANGED; li->new_cfg = cfg; multi_dhcp_notify_link_module(li->write_pipe); } else{ li->cfg = cfg; /* This is correct becuase if the information has not * changed, then there is no need to update the state. The * cfg must be updated due to leases and so on */ if(li->state != LINK_UP){ li->state = GOT_IP_DHCP; multi_dhcp_notify_link_module(li->write_pipe); } } g_static_rw_lock_writer_unlock(&(li->state_lock)); t_now = time(NULL); t_diff = t_now - di->req_sent_time; di->lease = cfg.lease; di->t1 = cfg.t1 ? cfg.t1 : cfg.lease / 2; di->t2 = cfg.t2 ? cfg.t2 : cfg.lease * 0.875; /* Not exactly sure what to do in this case */ assert(t_diff < di->t1 || t_diff < di->t2); assert(di->t1 < di->t2); /* Lease is from WHEN the request was sent */ di->lease -= t_diff; di->t1 -= t_diff; di->t2 -= t_diff; /* Convert values to be absolute */ di->lease += t_now; di->t1 += t_now; di->t2 += t_now; /* Every packet has been accounted for, so timers and everything can be reset */ di->req_sent_time = 0; //This will overflow, but it is ok. When the next timeout (T1) //is triggered, retrans_count will be increased by 1 and, thus, //be 0 again (but a little hackish) di->retrans_count = -1; /* New timeout event started */ di->output_timer = 1; } default: break; } }
/** * Returns 1 if retried, 0 if the command should fail, -1 for an internal * error */ static int handle_not_my_vbucket(lcb_server_t *c, protocol_binary_request_header *oldreq, struct lcb_command_data_st *oldct) { int idx; char *body; lcb_size_t nbody, nr; lcb_server_t *new_srv; struct lcb_command_data_st ct; protocol_binary_request_header req; hrtime_t now; if (c->instance->compat.type == LCB_CACHED_CONFIG) { lcb_schedule_config_cache_refresh(c->instance); } /* re-schedule command to new server */ idx = vbucket_found_incorrect_master(c->instance->vbucket_config, ntohs(oldreq->request.vbucket), (int)c->index); if (idx == -1) { return 0; } now = gethrtime(); if (oldct->real_start) { hrtime_t min_ok = now - (c->connection.timeout.usec * 1000); if (oldct->real_start < min_ok) { /** Timed out in a 'natural' manner */ return 0; } } req = *oldreq; lcb_assert((lcb_size_t)idx < c->instance->nservers); new_srv = c->instance->servers + idx; nr = lcb_ringbuffer_read(&c->cmd_log, req.bytes, sizeof(req)); lcb_assert(nr == sizeof(req)); req.request.opaque = ++c->instance->seqno; nbody = ntohl(req.request.bodylen); body = malloc(nbody); if (body == NULL) { lcb_error_handler(c->instance, LCB_CLIENT_ENOMEM, NULL); return -1; } nr = lcb_ringbuffer_read(&c->cmd_log, body, nbody); lcb_assert(nr == nbody); nr = lcb_ringbuffer_read(&c->output_cookies, &ct, sizeof(ct)); lcb_assert(nr == sizeof(ct)); /* Preserve the cookie and reset timestamp for the command. This * means that the library will retry the command until it will * get code different from LCB_NOT_MY_VBUCKET */ if (!ct.real_start) { ct.real_start = ct.start; } ct.start = now; lcb_server_retry_packet(new_srv, &ct, &req, sizeof(req)); /* FIXME dtrace instrumentation */ lcb_server_write_packet(new_srv, body, nbody); lcb_server_end_packet(new_srv); lcb_server_send_packets(new_srv); free(body); return 1; }
static int dhcp_get_offer(struct dhcp_context * context, int wait_ticks) { int error = 0; int gather_count = 0; const struct in_addr * ip; int last_rating = 0; int len; int n; int rating; struct dhcp * reply; struct in_addr server_id; struct socket * timer_arg; timer_arg = context->so; reply = dhcp_context_reply(context); timeout((timeout_fcn_t)dhcp_timeout, &timer_arg, wait_ticks); while (1) { error = receive_packet(context->so, context->reply, sizeof(context->reply), &n); if (error == 0) { dhcpol_t options; dprintf(("\ndhcp: received packet length %d\n", n)); if (n < (int)sizeof(struct dhcp)) { dprintf(("dhcp: packet is too short %d < %d\n", n, (int)sizeof(struct dhcp))); continue; } if (ntohl(reply->dp_xid) != context->xid || reply->dp_yiaddr.s_addr == 0 || reply->dp_yiaddr.s_addr == INADDR_BROADCAST || bcmp(reply->dp_chaddr, link_address(context->dl_p), link_address_length(context->dl_p)) != 0) { /* not for us */ continue; } (void)dhcpol_parse_packet(&options, reply, n); if (get_dhcp_msgtype(&options) != dhcp_msgtype_offer_e) { /* not an offer */ goto next_packet; } ip = (const struct in_addr *) dhcpol_find(&options, dhcptag_server_identifier_e, &len, NULL); if (ip == NULL || len < (int)sizeof(*ip)) { /* missing/invalid server identifier */ goto next_packet; } printf("dhcp: received OFFER: server " IP_FORMAT " IP address " IP_FORMAT "\n", IP_LIST(ip), IP_LIST(&reply->dp_yiaddr)); server_id = *ip; rating = rate_packet(&options); if (rating > last_rating) { context->iaddr = reply->dp_yiaddr; ip = (const struct in_addr *) dhcpol_find(&options, dhcptag_subnet_mask_e, &len, NULL); if (ip != NULL && len >= (int)sizeof(*ip)) { context->netmask = *ip; } ip = (const struct in_addr *) dhcpol_find(&options, dhcptag_router_e, &len, NULL); if (ip != NULL && len >= (int)sizeof(*ip)) { context->router = *ip; } context->server_id = server_id; } if (rating >= GOOD_RATING) { dhcpol_free(&options); /* packet is good enough */ untimeout((timeout_fcn_t)dhcp_timeout, &timer_arg); break; } if (gather_count == 0) { untimeout((timeout_fcn_t)dhcp_timeout, &timer_arg); timer_arg = context->so; timeout((timeout_fcn_t)dhcp_timeout, &timer_arg, hz * GATHER_TIME_SECS); } gather_count = 1; next_packet: dhcpol_free(&options); } else if ((error != EWOULDBLOCK)) { untimeout((timeout_fcn_t)dhcp_timeout, &timer_arg); break; } else if (timer_arg == NULL) { /* timed out */ if (gather_count != 0) { dprintf(("dhcp: gathering time has expired\n")); error = 0; } break; } else { socket_lock(context->so, 1); error = sbwait(&context->so->so_rcv); socket_unlock(context->so, 1); } } return (error); }
// application main method int main(int argc, char *argv[]) { // check if the output is a tty so we can use colors #ifdef WIN32 usecolor = 0; #else usecolor = isatty(1); #endif static struct option long_options[] = { {"color", no_argument, 0, 'c'}, {0, 0, 0, 0} }; while (1) { int c = getopt_long(argc, argv, "c", long_options, 0); if (c == -1) { break; } switch (c) { case 'c': usecolor = true; break; default: exit(1); } } // check for proper command line args if (optind != argc-1) { err("usage: %s [--color] file.osm.pbf", argv[0]); } // open specified file FILE *fp = fopen(argv[optind], "rb"); if (!fp) { err("can't open file '%s'", argv[optind]); } // read while the file has not reached its end while (!feof(fp)) { // storage of size, used multiple times int32_t sz; // read the first 4 bytes of the file, this is the size of the blob-header if (fread(&sz, sizeof(sz), 1, fp) != 1) { break; // end of file reached } // convert the size from network byte-order to host byte-order sz = ntohl(sz); // ensure the blob-header is smaller then MAX_BLOB_HEADER_SIZE if (sz > OSMPBF::max_blob_header_size) { err("blob-header-size is bigger then allowed (%u > %u)", sz, OSMPBF::max_blob_header_size); } // read the blob-header from the file if (fread(buffer, sz, 1, fp) != 1) { err("unable to read blob-header from file"); } // parse the blob-header from the read-buffer if (!blobheader.ParseFromArray(buffer, sz)) { err("unable to parse blob header"); } // tell about the blob-header info("\nBlobHeader (%d bytes)", sz); debug(" type = %s", blobheader.type().c_str()); // size of the following blob sz = blobheader.datasize(); debug(" datasize = %u", sz); // optional indexdata if (blobheader.has_indexdata()) { debug(" indexdata = %u bytes", blobheader.indexdata().size()); } // ensure the blob is smaller then MAX_BLOB_SIZE if (sz > OSMPBF::max_uncompressed_blob_size) { err("blob-size is bigger then allowed (%u > %u)", sz, OSMPBF::max_uncompressed_blob_size); } // read the blob from the file if (fread(buffer, sz, 1, fp) != 1) { err("unable to read blob from file"); } // parse the blob from the read-buffer if (!blob.ParseFromArray(buffer, sz)) { err("unable to parse blob"); } // tell about the blob-header info("Blob (%d bytes)", sz); // set when we find at least one data stream bool found_data = false; // if the blob has uncompressed data if (blob.has_raw()) { // we have at least one datastream found_data = true; // size of the blob-data sz = blob.raw().size(); // check that raw_size is set correctly if (sz != blob.raw_size()) { warn(" reports wrong raw_size: %u bytes", blob.raw_size()); } // tell about the blob-data debug(" contains uncompressed data: %u bytes", sz); // copy the uncompressed data over to the unpack_buffer memcpy(unpack_buffer, buffer, sz); } // if the blob has zlib-compressed data if (blob.has_zlib_data()) { // issue a warning if there is more than one data steam, a blob may only contain one data stream if (found_data) { warn(" contains several data streams"); } // we have at least one datastream found_data = true; // the size of the compressesd data sz = blob.zlib_data().size(); // tell about the compressed data debug(" contains zlib-compressed data: %u bytes", sz); debug(" uncompressed size: %u bytes", blob.raw_size()); // zlib information z_stream z; // next byte to decompress z.next_in = (unsigned char*) blob.zlib_data().c_str(); // number of bytes to decompress z.avail_in = sz; // place of next decompressed byte z.next_out = (unsigned char*) unpack_buffer; // space for decompressed data z.avail_out = blob.raw_size(); // misc z.zalloc = Z_NULL; z.zfree = Z_NULL; z.opaque = Z_NULL; if (inflateInit(&z) != Z_OK) { err(" failed to init zlib stream"); } if (inflate(&z, Z_FINISH) != Z_STREAM_END) { err(" failed to inflate zlib stream"); } if (inflateEnd(&z) != Z_OK) { err(" failed to deinit zlib stream"); } // unpacked size sz = z.total_out; } // if the blob has lzma-compressed data if (blob.has_lzma_data()) { // issue a warning if there is more than one data steam, a blob may only contain one data stream if (found_data) { warn(" contains several data streams"); } // we have at least one datastream found_data = true; // tell about the compressed data debug(" contains lzma-compressed data: %u bytes", blob.lzma_data().size()); debug(" uncompressed size: %u bytes", blob.raw_size()); // issue a warning, lzma compression is not yet supported err(" lzma-decompression is not supported"); } // check we have at least one data-stream if (!found_data) { err(" does not contain any known data stream"); } // switch between different blob-types if (blobheader.type() == "OSMHeader") { // tell about the OSMHeader blob info(" OSMHeader"); // parse the HeaderBlock from the blob if (!headerblock.ParseFromArray(unpack_buffer, sz)) { err("unable to parse header block"); } // tell about the bbox if (headerblock.has_bbox()) { OSMPBF::HeaderBBox bbox = headerblock.bbox(); debug(" bbox: %.7f,%.7f,%.7f,%.7f", (double)bbox.left() / OSMPBF::lonlat_resolution, (double)bbox.bottom() / OSMPBF::lonlat_resolution, (double)bbox.right() / OSMPBF::lonlat_resolution, (double)bbox.top() / OSMPBF::lonlat_resolution); } // tell about the required features for (int i = 0, l = headerblock.required_features_size(); i < l; i++) { debug(" required_feature: %s", headerblock.required_features(i).c_str()); } // tell about the optional features for (int i = 0, l = headerblock.optional_features_size(); i < l; i++) { debug(" optional_feature: %s", headerblock.optional_features(i).c_str()); } // tell about the writing program if (headerblock.has_writingprogram()) { debug(" writingprogram: %s", headerblock.writingprogram().c_str()); } // tell about the source if (headerblock.has_source()) { debug(" source: %s", headerblock.source().c_str()); } } else if (blobheader.type() == "OSMData") { // tell about the OSMData blob info(" OSMData"); // parse the PrimitiveBlock from the blob if (!primblock.ParseFromArray(unpack_buffer, sz)) { err("unable to parse primitive block"); } // tell about the block's meta info debug(" granularity: %u", primblock.granularity()); debug(" lat_offset: %u", primblock.lat_offset()); debug(" lon_offset: %u", primblock.lon_offset()); debug(" date_granularity: %u", primblock.date_granularity()); // tell about the stringtable debug(" stringtable: %u items", primblock.stringtable().s_size()); // number of PrimitiveGroups debug(" primitivegroups: %u groups", primblock.primitivegroup_size()); // iterate over all PrimitiveGroups for (int i = 0, l = primblock.primitivegroup_size(); i < l; i++) { // one PrimitiveGroup from the the Block OSMPBF::PrimitiveGroup pg = primblock.primitivegroup(i); bool found_items=false; // tell about nodes if (pg.nodes_size() > 0) { found_items = true; debug(" nodes: %d", pg.nodes_size()); if (pg.nodes(0).has_info()) { debug(" with meta-info"); } } // tell about dense nodes if (pg.has_dense()) { found_items = true; debug(" dense nodes: %d", pg.dense().id_size()); if (pg.dense().has_denseinfo()) { debug(" with meta-info"); } } // tell about ways if (pg.ways_size() > 0) { found_items = true; debug(" ways: %d", pg.ways_size()); if (pg.ways(0).has_info()) { debug(" with meta-info"); } } // tell about relations if (pg.relations_size() > 0) { found_items = true; debug(" relations: %d", pg.relations_size()); if (pg.relations(0).has_info()) { debug(" with meta-info"); } } if (!found_items) { warn(" contains no items"); } } } else { // unknown blob type warn(" unknown blob type: %s", blobheader.type().c_str()); } } // close the file pointer fclose(fp); // clean up the protobuf lib google::protobuf::ShutdownProtobufLibrary(); }
/* Create "opt_name=opt_value" string */ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_option *type_p, const char *opt_name) { unsigned upper_length; int len, type, optlen; uint16_t val_u16; int16_t val_s16; uint32_t val_u32; int32_t val_s32; char *dest, *ret; /* option points to OPT_DATA, need to go back and get OPT_LEN */ len = option[OPT_LEN - OPT_DATA]; type = type_p->flags & TYPE_MASK; optlen = dhcp_option_lengths[type]; upper_length = len_of_option_as_string[type] * (len / optlen); dest = ret = xmalloc(upper_length + strlen(opt_name) + 2); dest += sprintf(ret, "%s=", opt_name); while (len >= optlen) { switch (type) { case OPTION_IP_PAIR: dest += sprint_nip(dest, "", option); *dest++ = '/'; option += 4; optlen = 4; case OPTION_IP: /* Works regardless of host byte order. */ dest += sprint_nip(dest, "", option); break; case OPTION_BOOLEAN: dest += sprintf(dest, *option ? "yes" : "no"); break; case OPTION_U8: dest += sprintf(dest, "%u", *option); break; case OPTION_U16: move_from_unaligned16(val_u16, option); dest += sprintf(dest, "%u", ntohs(val_u16)); break; case OPTION_S16: move_from_unaligned16(val_s16, option); dest += sprintf(dest, "%d", ntohs(val_s16)); break; case OPTION_U32: move_from_unaligned32(val_u32, option); dest += sprintf(dest, "%lu", (unsigned long) ntohl(val_u32)); break; case OPTION_S32: move_from_unaligned32(val_s32, option); dest += sprintf(dest, "%ld", (long) ntohl(val_s32)); break; case OPTION_STRING: memcpy(dest, option, len); dest[len] = '\0'; return ret; /* Short circuit this case */ case OPTION_STATIC_ROUTES: { /* Option binary format: * mask [one byte, 0..32] * ip [big endian, 0..4 bytes depending on mask] * router [big endian, 4 bytes] * may be repeated * * We convert it to a string "IP/MASK ROUTER IP2/MASK2 ROUTER2" */ const char *pfx = ""; while (len >= 1 + 4) { /* mask + 0-byte ip + router */ uint32_t nip; uint8_t *p; unsigned mask; int bytes; mask = *option++; if (mask > 32) break; len--; nip = 0; p = (void*) &nip; bytes = (mask + 7) / 8; /* 0 -> 0, 1..8 -> 1, 9..16 -> 2 etc */ while (--bytes >= 0) { *p++ = *option++; len--; } if (len < 4) break; /* print ip/mask */ dest += sprint_nip(dest, pfx, (void*) &nip); pfx = " "; dest += sprintf(dest, "/%u ", mask); /* print router */ dest += sprint_nip(dest, "", option); option += 4; len -= 4; } return ret; } #if ENABLE_FEATURE_UDHCP_RFC3397 case OPTION_STR1035: /* unpack option into dest; use ret for prefix (i.e., "optname=") */ dest = dname_dec(option, len, ret); if (dest) { free(ret); return dest; } /* error. return "optname=" string */ return ret; #endif } option += optlen; len -= optlen; if (len <= 0) break; *dest++ = ' '; *dest = '\0'; } return ret; }
/* Appends a string representation of 'match' to 's'. If 'priority' is * different from OFP_DEFAULT_PRIORITY, includes it in 's'. */ void match_format(const struct match *match, struct ds *s, unsigned int priority) { const struct flow_wildcards *wc = &match->wc; size_t start_len = s->length; const struct flow *f = &match->flow; bool skip_type = false; bool skip_proto = false; int i; BUILD_ASSERT_DECL(FLOW_WC_SEQ == 27); if (priority != OFP_DEFAULT_PRIORITY) { ds_put_format(s, "priority=%u,", priority); } format_uint32_masked(s, "pkt_mark", f->pkt_mark, wc->masks.pkt_mark); if (wc->masks.recirc_id) { format_uint32_masked(s, "recirc_id", f->recirc_id, wc->masks.recirc_id); } if (f->dp_hash && wc->masks.dp_hash) { format_uint32_masked(s, "dp_hash", f->dp_hash, wc->masks.dp_hash); } if (wc->masks.skb_priority) { ds_put_format(s, "skb_priority=%#"PRIx32",", f->skb_priority); } if (wc->masks.dl_type) { skip_type = true; if (f->dl_type == htons(ETH_TYPE_IP)) { if (wc->masks.nw_proto) { skip_proto = true; if (f->nw_proto == IPPROTO_ICMP) { ds_put_cstr(s, "icmp,"); } else if (f->nw_proto == IPPROTO_IGMP) { ds_put_cstr(s, "igmp,"); } else if (f->nw_proto == IPPROTO_TCP) { ds_put_cstr(s, "tcp,"); } else if (f->nw_proto == IPPROTO_UDP) { ds_put_cstr(s, "udp,"); } else if (f->nw_proto == IPPROTO_SCTP) { ds_put_cstr(s, "sctp,"); } else { ds_put_cstr(s, "ip,"); skip_proto = false; } } else { ds_put_cstr(s, "ip,"); } } else if (f->dl_type == htons(ETH_TYPE_IPV6)) { if (wc->masks.nw_proto) { skip_proto = true; if (f->nw_proto == IPPROTO_ICMPV6) { ds_put_cstr(s, "icmp6,"); } else if (f->nw_proto == IPPROTO_TCP) { ds_put_cstr(s, "tcp6,"); } else if (f->nw_proto == IPPROTO_UDP) { ds_put_cstr(s, "udp6,"); } else if (f->nw_proto == IPPROTO_SCTP) { ds_put_cstr(s, "sctp6,"); } else { ds_put_cstr(s, "ipv6,"); skip_proto = false; } } else { ds_put_cstr(s, "ipv6,"); } } else if (f->dl_type == htons(ETH_TYPE_ARP)) { ds_put_cstr(s, "arp,"); } else if (f->dl_type == htons(ETH_TYPE_RARP)) { ds_put_cstr(s, "rarp,"); } else if (f->dl_type == htons(ETH_TYPE_MPLS)) { ds_put_cstr(s, "mpls,"); } else if (f->dl_type == htons(ETH_TYPE_MPLS_MCAST)) { ds_put_cstr(s, "mplsm,"); } else { skip_type = false; } } for (i = 0; i < FLOW_N_REGS; i++) { #define REGNAME_LEN 20 char regname[REGNAME_LEN]; if (snprintf(regname, REGNAME_LEN, "reg%d", i) >= REGNAME_LEN) { strcpy(regname, "reg?"); } format_uint32_masked(s, regname, f->regs[i], wc->masks.regs[i]); } format_flow_tunnel(s, match); format_be64_masked(s, "metadata", f->metadata, wc->masks.metadata); if (wc->masks.in_port.ofp_port) { ds_put_cstr(s, "in_port="); ofputil_format_port(f->in_port.ofp_port, s); ds_put_char(s, ','); } if (wc->masks.vlan_tci) { ovs_be16 vid_mask = wc->masks.vlan_tci & htons(VLAN_VID_MASK); ovs_be16 pcp_mask = wc->masks.vlan_tci & htons(VLAN_PCP_MASK); ovs_be16 cfi = wc->masks.vlan_tci & htons(VLAN_CFI); if (cfi && f->vlan_tci & htons(VLAN_CFI) && (!vid_mask || vid_mask == htons(VLAN_VID_MASK)) && (!pcp_mask || pcp_mask == htons(VLAN_PCP_MASK)) && (vid_mask || pcp_mask)) { if (vid_mask) { ds_put_format(s, "dl_vlan=%"PRIu16",", vlan_tci_to_vid(f->vlan_tci)); } if (pcp_mask) { ds_put_format(s, "dl_vlan_pcp=%d,", vlan_tci_to_pcp(f->vlan_tci)); } } else if (wc->masks.vlan_tci == htons(0xffff)) { ds_put_format(s, "vlan_tci=0x%04"PRIx16",", ntohs(f->vlan_tci)); } else { ds_put_format(s, "vlan_tci=0x%04"PRIx16"/0x%04"PRIx16",", ntohs(f->vlan_tci), ntohs(wc->masks.vlan_tci)); } } format_eth_masked(s, "dl_src", f->dl_src, wc->masks.dl_src); format_eth_masked(s, "dl_dst", f->dl_dst, wc->masks.dl_dst); if (!skip_type && wc->masks.dl_type) { ds_put_format(s, "dl_type=0x%04"PRIx16",", ntohs(f->dl_type)); } if (f->dl_type == htons(ETH_TYPE_IPV6)) { format_ipv6_netmask(s, "ipv6_src", &f->ipv6_src, &wc->masks.ipv6_src); format_ipv6_netmask(s, "ipv6_dst", &f->ipv6_dst, &wc->masks.ipv6_dst); if (wc->masks.ipv6_label) { if (wc->masks.ipv6_label == OVS_BE32_MAX) { ds_put_format(s, "ipv6_label=0x%05"PRIx32",", ntohl(f->ipv6_label)); } else { ds_put_format(s, "ipv6_label=0x%05"PRIx32"/0x%05"PRIx32",", ntohl(f->ipv6_label), ntohl(wc->masks.ipv6_label)); } } } else if (f->dl_type == htons(ETH_TYPE_ARP) || f->dl_type == htons(ETH_TYPE_RARP)) { format_ip_netmask(s, "arp_spa", f->nw_src, wc->masks.nw_src); format_ip_netmask(s, "arp_tpa", f->nw_dst, wc->masks.nw_dst); } else { format_ip_netmask(s, "nw_src", f->nw_src, wc->masks.nw_src); format_ip_netmask(s, "nw_dst", f->nw_dst, wc->masks.nw_dst); } if (!skip_proto && wc->masks.nw_proto) { if (f->dl_type == htons(ETH_TYPE_ARP) || f->dl_type == htons(ETH_TYPE_RARP)) { ds_put_format(s, "arp_op=%"PRIu8",", f->nw_proto); } else { ds_put_format(s, "nw_proto=%"PRIu8",", f->nw_proto); } } if (f->dl_type == htons(ETH_TYPE_ARP) || f->dl_type == htons(ETH_TYPE_RARP)) { format_eth_masked(s, "arp_sha", f->arp_sha, wc->masks.arp_sha); format_eth_masked(s, "arp_tha", f->arp_tha, wc->masks.arp_tha); } if (wc->masks.nw_tos & IP_DSCP_MASK) { ds_put_format(s, "nw_tos=%"PRIu8",", f->nw_tos & IP_DSCP_MASK); } if (wc->masks.nw_tos & IP_ECN_MASK) { ds_put_format(s, "nw_ecn=%"PRIu8",", f->nw_tos & IP_ECN_MASK); } if (wc->masks.nw_ttl) { ds_put_format(s, "nw_ttl=%"PRIu8",", f->nw_ttl); } if (wc->masks.mpls_lse[0] & htonl(MPLS_LABEL_MASK)) { ds_put_format(s, "mpls_label=%"PRIu32",", mpls_lse_to_label(f->mpls_lse[0])); } if (wc->masks.mpls_lse[0] & htonl(MPLS_TC_MASK)) { ds_put_format(s, "mpls_tc=%"PRIu8",", mpls_lse_to_tc(f->mpls_lse[0])); } if (wc->masks.mpls_lse[0] & htonl(MPLS_TTL_MASK)) { ds_put_format(s, "mpls_ttl=%"PRIu8",", mpls_lse_to_ttl(f->mpls_lse[0])); } if (wc->masks.mpls_lse[0] & htonl(MPLS_BOS_MASK)) { ds_put_format(s, "mpls_bos=%"PRIu8",", mpls_lse_to_bos(f->mpls_lse[0])); } format_be32_masked(s, "mpls_lse1", f->mpls_lse[1], wc->masks.mpls_lse[1]); format_be32_masked(s, "mpls_lse2", f->mpls_lse[2], wc->masks.mpls_lse[2]); switch (wc->masks.nw_frag) { case FLOW_NW_FRAG_ANY | FLOW_NW_FRAG_LATER: ds_put_format(s, "nw_frag=%s,", f->nw_frag & FLOW_NW_FRAG_ANY ? (f->nw_frag & FLOW_NW_FRAG_LATER ? "later" : "first") : (f->nw_frag & FLOW_NW_FRAG_LATER ? "<error>" : "no")); break; case FLOW_NW_FRAG_ANY: ds_put_format(s, "nw_frag=%s,", f->nw_frag & FLOW_NW_FRAG_ANY ? "yes" : "no"); break; case FLOW_NW_FRAG_LATER: ds_put_format(s, "nw_frag=%s,", f->nw_frag & FLOW_NW_FRAG_LATER ? "later" : "not_later"); break; } if (f->dl_type == htons(ETH_TYPE_IP) && f->nw_proto == IPPROTO_ICMP) { format_be16_masked(s, "icmp_type", f->tp_src, wc->masks.tp_src); format_be16_masked(s, "icmp_code", f->tp_dst, wc->masks.tp_dst); } else if (f->dl_type == htons(ETH_TYPE_IP) && f->nw_proto == IPPROTO_IGMP) { format_be16_masked(s, "igmp_type", f->tp_src, wc->masks.tp_src); format_be16_masked(s, "igmp_code", f->tp_dst, wc->masks.tp_dst); } else if (f->dl_type == htons(ETH_TYPE_IPV6) && f->nw_proto == IPPROTO_ICMPV6) { format_be16_masked(s, "icmp_type", f->tp_src, wc->masks.tp_src); format_be16_masked(s, "icmp_code", f->tp_dst, wc->masks.tp_dst); format_ipv6_netmask(s, "nd_target", &f->nd_target, &wc->masks.nd_target); format_eth_masked(s, "nd_sll", f->arp_sha, wc->masks.arp_sha); format_eth_masked(s, "nd_tll", f->arp_tha, wc->masks.arp_tha); } else { format_be16_masked(s, "tp_src", f->tp_src, wc->masks.tp_src); format_be16_masked(s, "tp_dst", f->tp_dst, wc->masks.tp_dst); } if (is_ip_any(f) && f->nw_proto == IPPROTO_TCP && wc->masks.tcp_flags) { uint16_t mask = TCP_FLAGS(wc->masks.tcp_flags); if (mask == TCP_FLAGS(OVS_BE16_MAX)) { ds_put_cstr(s, "tcp_flags="); if (f->tcp_flags) { format_flags(s, packet_tcp_flag_to_string, ntohs(f->tcp_flags), '|'); } else { ds_put_cstr(s, "0"); /* Zero flags. */ } } else if (mask) { format_flags_masked(s, "tcp_flags", packet_tcp_flag_to_string, ntohs(f->tcp_flags), mask); } } if (s->length > start_len && ds_last(s) == ',') { s->length--; } }
/* * Parallel to llc_rtrequest. */ static void arp_rtrequest( int req, struct rtentry *rt, __unused struct sockaddr *sa) { struct sockaddr *gate = rt->rt_gateway; struct llinfo_arp *la = rt->rt_llinfo; static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK, 0, 0, 0, 0, 0, {0}}; struct timeval timenow; if (!arpinit_done) { panic("%s: ARP has not been initialized", __func__); /* NOTREACHED */ } lck_mtx_assert(rnh_lock, LCK_MTX_ASSERT_OWNED); RT_LOCK_ASSERT_HELD(rt); if (rt->rt_flags & RTF_GATEWAY) return; getmicrotime(&timenow); switch (req) { case RTM_ADD: /* * XXX: If this is a manually added route to interface * such as older version of routed or gated might provide, * restore cloning bit. */ if ((rt->rt_flags & RTF_HOST) == 0 && SIN(rt_mask(rt))->sin_addr.s_addr != 0xffffffff) rt->rt_flags |= RTF_CLONING; if (rt->rt_flags & RTF_CLONING) { /* * Case 1: This route should come from a route to iface. */ if (rt_setgate(rt, rt_key(rt), (struct sockaddr *)&null_sdl) == 0) { gate = rt->rt_gateway; SDL(gate)->sdl_type = rt->rt_ifp->if_type; SDL(gate)->sdl_index = rt->rt_ifp->if_index; /* * In case we're called before 1.0 sec. * has elapsed. */ rt->rt_expire = MAX(timenow.tv_sec, 1); } break; } /* Announce a new entry if requested. */ if (rt->rt_flags & RTF_ANNOUNCE) { RT_UNLOCK(rt); dlil_send_arp(rt->rt_ifp, ARPOP_REQUEST, SDL(gate), rt_key(rt), NULL, rt_key(rt)); RT_LOCK(rt); } /*FALLTHROUGH*/ case RTM_RESOLVE: if (gate->sa_family != AF_LINK || gate->sa_len < sizeof(null_sdl)) { if (log_arp_warnings) log(LOG_DEBUG, "arp_rtrequest: bad gateway value\n"); break; } SDL(gate)->sdl_type = rt->rt_ifp->if_type; SDL(gate)->sdl_index = rt->rt_ifp->if_index; if (la != 0) break; /* This happens on a route change */ /* * Case 2: This route may come from cloning, or a manual route * add with a LL address. */ rt->rt_llinfo = la = arp_llinfo_alloc(); if (la == NULL) { if (log_arp_warnings) log(LOG_DEBUG, "%s: malloc failed\n", __func__); break; } rt->rt_llinfo_free = arp_llinfo_free; arp_inuse++, arp_allocated++; Bzero(la, sizeof(*la)); la->la_rt = rt; rt->rt_flags |= RTF_LLINFO; LIST_INSERT_HEAD(&llinfo_arp, la, la_le); /* * This keeps the multicast addresses from showing up * in `arp -a' listings as unresolved. It's not actually * functional. Then the same for broadcast. */ if (IN_MULTICAST(ntohl(SIN(rt_key(rt))->sin_addr.s_addr))) { RT_UNLOCK(rt); dlil_resolve_multi(rt->rt_ifp, rt_key(rt), gate, sizeof(struct sockaddr_dl)); RT_LOCK(rt); rt->rt_expire = 0; } else if (in_broadcast(SIN(rt_key(rt))->sin_addr, rt->rt_ifp)) { struct sockaddr_dl *gate_ll = SDL(gate); size_t broadcast_len; ifnet_llbroadcast_copy_bytes(rt->rt_ifp, LLADDR(gate_ll), sizeof(gate_ll->sdl_data), &broadcast_len); gate_ll->sdl_alen = broadcast_len; gate_ll->sdl_family = AF_LINK; gate_ll->sdl_len = sizeof(struct sockaddr_dl); /* In case we're called before 1.0 sec. has elapsed */ rt->rt_expire = MAX(timenow.tv_sec, 1); } if (SIN(rt_key(rt))->sin_addr.s_addr == (IA_SIN(rt->rt_ifa))->sin_addr.s_addr) { /* * This test used to be * if (loif.if_flags & IFF_UP) * It allowed local traffic to be forced * through the hardware by configuring the loopback down. * However, it causes problems during network configuration * for boards that can't receive packets they send. * It is now necessary to clear "useloopback" and remove * the route to force traffic out to the hardware. */ rt->rt_expire = 0; ifnet_lladdr_copy_bytes(rt->rt_ifp, LLADDR(SDL(gate)), SDL(gate)->sdl_alen = 6); if (useloopback) { #if IFNET_ROUTE_REFCNT /* Adjust route ref count for the interfaces */ if (rt->rt_if_ref_fn != NULL && rt->rt_ifp != lo_ifp) { rt->rt_if_ref_fn(lo_ifp, 1); rt->rt_if_ref_fn(rt->rt_ifp, -1); } #endif /* IFNET_ROUTE_REFCNT */ rt->rt_ifp = lo_ifp; } } break; case RTM_DELETE: if (la == 0) break; arp_inuse--; /* * Unchain it but defer the actual freeing until the route * itself is to be freed. rt->rt_llinfo still points to * llinfo_arp, and likewise, la->la_rt still points to this * route entry, except that RTF_LLINFO is now cleared. */ LIST_REMOVE(la, la_le); la->la_le.le_next = NULL; la->la_le.le_prev = NULL; rt->rt_flags &= ~RTF_LLINFO; if (la->la_hold != NULL) m_freem(la->la_hold); la->la_hold = NULL; } }
/*------------------------------------ convertBufferToAtoms ---*/ t_atom * convertBufferToAtoms(void * xx, t_handle aBuffer, sockaddr_in & sender, long & numAtoms, const long numBytes, const bool rawMode) { long outputSize; t_atom * result = NULL; unsigned char * walker = reinterpret_cast<unsigned char *>(*aBuffer); if (rawMode) { outputSize = numBytes + 2; result = GET_BYTES(outputSize, t_atom); if (result) { t_atom * thisAtom = result; char hostAddr[NI_MAXHOST + 1]; getnameinfo(reinterpret_cast<sockaddr *>(&sender), sizeof(sender), hostAddr, sizeof(hostAddr), NULL, 0, NI_NUMERICHOST); atom_setsym(thisAtom, gensym(hostAddr)); ++thisAtom; atom_setlong(thisAtom, TO_INT(sender.sin_port)); ++thisAtom; for (short ii = 0; ii < numBytes; ++ii, ++thisAtom, ++walker) { atom_setlong(thisAtom, TO_INT(*walker)); } } } else { short numElements; short sanityCheck; long calcBytes; bool okSoFar = true; memcpy(&numElements, walker, sizeof(numElements)); numElements = ntohs(numElements); memcpy(&sanityCheck, walker + sizeof(numElements), sizeof(sanityCheck)); sanityCheck = ntohs(sanityCheck); calcBytes = -(numElements + sanityCheck); walker += (sizeof(numElements) + sizeof(sanityCheck)); outputSize = numElements + 2; result = GET_BYTES(outputSize, t_atom); if (result) { t_atom * thisAtom = result; unsigned char * lastByteInBuffer = walker + calcBytes; short chunkSize; unsigned char baseElementType = *walker; // !!! unsigned char elementType = baseElementType; long dummy; char hostAddr[NI_MAXHOST + 1]; getnameinfo(reinterpret_cast<sockaddr *>(&sender), sizeof(sender), hostAddr, sizeof(hostAddr), NULL, 0, NI_NUMERICHOST); atom_setsym(thisAtom, gensym(hostAddr)); ++thisAtom; atom_setlong(thisAtom, TO_INT(sender.sin_port)); ++thisAtom; ++walker; for (long element_index = 0; okSoFar && (element_index < numElements); ++element_index, ++thisAtom) { if (walker > lastByteInBuffer) { /* We should never get here, but just in case: */ LOG_ERROR_1(xx, OUTPUT_PREFIX "ran off end of receive buffer!") okSoFar = false; } if (A_GIMME == baseElementType) { /* A mixed vector: get the type */ elementType = *walker; ++walker; } switch (elementType) { case A_FLOAT: if ((walker + sizeof(float)) > lastByteInBuffer) { LOG_ERROR_1(xx, OUTPUT_PREFIX "ran off end of receive buffer!") okSoFar = false; } else { memcpy(&dummy, walker, sizeof(dummy)); atom_setfloat(thisAtom, ntohl(*reinterpret_cast<float *>(&dummy))); walker += sizeof(float); } break; case A_LONG: if ((walker + sizeof(long)) > lastByteInBuffer) { LOG_ERROR_1(xx, OUTPUT_PREFIX "ran off end of receive buffer!") okSoFar = false; } else { memcpy(&dummy, walker, sizeof(long)); atom_setlong(thisAtom, ntohl(dummy)); walker += sizeof(long); } break; case A_SYM: if ((walker + sizeof(chunkSize)) > lastByteInBuffer) { LOG_ERROR_1(xx, OUTPUT_PREFIX "ran off end of receive buffer!") okSoFar = false; } else { memcpy(&chunkSize, walker, sizeof(chunkSize)); chunkSize = ntohs(chunkSize); walker += sizeof(chunkSize); if ((walker + chunkSize) > lastByteInBuffer) { LOG_ERROR_1(xx, OUTPUT_PREFIX "ran off end of receive buffer!") okSoFar = false; } else { atom_setsym(thisAtom, gensym(reinterpret_cast<char *>(walker))); walker += chunkSize; } } break; case A_SEMI: case A_COMMA: case A_DOLLAR: case A_DOLLSYM: thisAtom->a_type = elementType; break; default: LOG_ERROR_2(xx, OUTPUT_PREFIX "unexpected atom type seen - atom %d", static_cast<int>(element_index)) okSoFar = false; break; } } if (! okSoFar) { FREE_BYTES(result); outputSize = 0; } } *aBuffer = reinterpret_cast<char *>(walker); } numAtoms = outputSize; return result; } // convertBufferToAtoms
/* we receive a connection acknowledgement from the server, * consisting of nothing more than a status report. If success, * then we initiate authentication method */ static pmix_status_t recv_connect_ack(int sd) { pmix_status_t reply; pmix_status_t rc; struct timeval tv, save; pmix_socklen_t sz; bool sockopt = true; uint32_t u32; char nspace[PMIX_MAX_NSLEN+1]; pmix_output_verbose(2, pmix_globals.debug_output, "pmix: RECV CONNECT ACK FROM SERVER"); /* get the current timeout value so we can reset to it */ sz = sizeof(save); if (0 != getsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (void*)&save, &sz)) { if (ENOPROTOOPT == errno) { sockopt = false; } else { return PMIX_ERR_UNREACH; } } else { /* set a timeout on the blocking recv so we don't hang */ tv.tv_sec = 2; tv.tv_usec = 0; if (0 != setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv))) { pmix_output_verbose(2, pmix_globals.debug_output, "pmix: recv_connect_ack could not setsockopt SO_RCVTIMEO"); return PMIX_ERR_UNREACH; } } /* receive the status reply */ rc = pmix_ptl_base_recv_blocking(sd, (char*)&u32, sizeof(uint32_t)); if (PMIX_SUCCESS != rc) { PMIX_ERROR_LOG(rc); return rc; } reply = ntohl(u32); if (PMIX_PROC_IS_CLIENT) { /* see if they want us to do the handshake */ if (PMIX_ERR_READY_FOR_HANDSHAKE == reply) { PMIX_PSEC_CLIENT_HANDSHAKE(rc, pmix_client_globals.myserver, sd); if (PMIX_SUCCESS != rc) { return rc; } } else if (PMIX_SUCCESS != reply) { return reply; } pmix_output_verbose(2, pmix_globals.debug_output, "pmix: RECV CONNECT CONFIRMATION"); /* receive our index into the server's client array */ rc = pmix_ptl_base_recv_blocking(sd, (char*)&u32, sizeof(uint32_t)); if (PMIX_SUCCESS != rc) { PMIX_ERROR_LOG(rc); return rc; } pmix_globals.pindex = ntohl(u32); } else { // we are a tool /* if the status indicates an error, then we are done */ if (PMIX_SUCCESS != reply) { PMIX_ERROR_LOG(reply); return reply; } /* recv our nspace */ rc = pmix_ptl_base_recv_blocking(sd, (char*)&pmix_globals.myid.nspace, PMIX_MAX_NSLEN+1); if (PMIX_SUCCESS != rc) { PMIX_ERROR_LOG(rc); return rc; } /* our rank is always zero */ pmix_globals.myid.rank = 0; /* get the server's nspace and rank so we can send to it */ pmix_client_globals.myserver->info = PMIX_NEW(pmix_rank_info_t); pmix_client_globals.myserver->nptr = PMIX_NEW(pmix_nspace_t); pmix_ptl_base_recv_blocking(sd, (char*)nspace, PMIX_MAX_NSLEN+1); pmix_client_globals.myserver->nptr->nspace = strdup(nspace); pmix_client_globals.myserver->info->pname.nspace = strdup(nspace); pmix_ptl_base_recv_blocking(sd, (char*)&(pmix_client_globals.myserver->info->pname.rank), sizeof(int)); pmix_output_verbose(2, pmix_globals.debug_output, "pmix: RECV CONNECT CONFIRMATION FOR TOOL %s:%d FROM SERVER %s:%d", pmix_globals.myid.nspace, pmix_globals.myid.rank, pmix_client_globals.myserver->info->pname.nspace, pmix_client_globals.myserver->info->pname.rank); /* get the returned status from the security handshake */ pmix_ptl_base_recv_blocking(sd, (char*)&reply, sizeof(pmix_status_t)); if (PMIX_SUCCESS != reply) { /* see if they want us to do the handshake */ if (PMIX_ERR_READY_FOR_HANDSHAKE == reply) { PMIX_PSEC_CLIENT_HANDSHAKE(reply, pmix_client_globals.myserver, sd); if (PMIX_SUCCESS != reply) { return reply; } /* if the handshake succeeded, then fall thru to the next step */ } else { return reply; } } } if (sockopt) { if (0 != setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, &save, sz)) { return PMIX_ERR_UNREACH; } } return PMIX_SUCCESS; }
void * thread_read_write (void *arg) { struct thread_info *info = (struct thread_info *) arg; int i, ret; int id, fd; /* for request */ u_int32_t reqx, reqy; unsigned long boffset, nblock; struct sockaddr_in *serv_addr; struct key_request_packet kreq; /* for read */ u_int32_t resx, resy; struct sockaddr_in addr; socklen_t addrlen; struct key_response_packet kresp; int kresperr, krespsuberr, krespkeylen; struct timeval start, end, res; double time; int success; unsigned long send_count, read_count; id = info->id; memset (&info->stats, 0, sizeof (struct horus_stats)); send_count = read_count = 0; fd = socket (PF_INET, SOCK_DGRAM, 0); if (fd < 0) { printf ("thread[%d]: Unable to open socket!: %s\n", id, strerror (errno)); return NULL; } serv_addr = info->serv_addr; boffset = info->boffset; nblock = info->nblock; memset (&kreq, 0, sizeof (kreq)); reqx = info->level; kreq.x = htonl (reqx); strncpy (kreq.filename, info->filename, sizeof (kreq.filename)); if (benchmark || horus_verbose) printf ("thread[%d]: server %s:%d bsize %d boffset %lu nblock %lu\n", id, info->server, ntohs (serv_addr->sin_port), HORUS_BLOCK_SIZE, boffset, nblock); if (spinwait) { fcntl (fd, F_SETFL, O_NONBLOCK); printf ("thread[%d]: spinwait: usleep %d nanosleep %ld " "nsend %d nread %d\n", id, useconds, nanoseconds, nsend, nread); } if (benchmark) gettimeofday (&start, NULL); for (i = 0; i < nblock; i++) { reqy = boffset + i; kreq.y = htonl (reqy); success = 0; send_count = nsend; do { ret = sendto (fd, &kreq, sizeof (key_request_packet), 0, (struct sockaddr *) serv_addr, sizeof (struct sockaddr_in)); send_count--; if (ret != sizeof (key_request_packet)) { if (horus_debug) printf ("thread[%d]: sendto(): failed: %d " "send_count: %ld\n", id, ret, send_count); info->stats.sendfail++; continue; } else { if (horus_debug) printf ("thread[%d]: request %d,%d send_count: %ld\n", id, reqx, reqy, send_count); } read_count = nread; do { if (spinwait) { if (useconds) usleep (useconds); if (nanoseconds) { struct timespec nanospec; nanospec.tv_sec = 0; nanospec.tv_nsec = nanoseconds; nanosleep (&nanospec, NULL); } } addrlen = sizeof (struct sockaddr_in); ret = recvfrom (fd, &kresp, sizeof (key_response_packet), 0, (struct sockaddr *) &addr, &addrlen); read_count--; if (ret != sizeof (key_response_packet)) { if (horus_debug) printf ("thread[%d]: recvfrom(): failed: %d " "read_count: %ld\n", id, ret, read_count); info->stats.recvfail++; continue; } else { if (horus_debug) printf ("thread[%d]: recvfrom(): received %d\n", id, ret); resx = ntohl (kresp.x); resy = ntohl (kresp.y); if (resx == reqx && resy == reqy) success++; else { if (horus_debug) printf ("thread[%d]: mismatch: " "req: %d,%d: resp: %d,%d\n", id, reqx, reqy, resx, resy); info->stats.resmismatch++; } } } while (! success && read_count > 0); } while (! success && send_count > 0); info->stats.sendretry += nsend - send_count - 1; info->stats.recvretry += nread - read_count - 1; if (! success) { if (horus_verbose) printf ("thread[%d]: give up K_%d,%d: resend: %lu reread: %lu\n", id, reqx, reqy, send_count, read_count); info->stats.giveup++; continue; } info->stats.success++; kresperr = (int) ntohs (kresp.err); krespsuberr = (int) ntohs (kresp.suberr); krespkeylen = (int) ntohl (kresp.key_len); horus_stats_record (&info->stats, kresperr, krespsuberr); if (horus_verbose && ! benchmark) { if (kresperr) printf ("thread[%d]: err = %d : %s\n", id, kresperr, horus_strerror (kresperr)); if (krespsuberr) printf ("thread[%d]: suberr = %d : %s\n", id, krespsuberr, strerror (krespsuberr)); if (! kresperr) printf ("thread[%d]: key_%d,%d: key_%d,%d/%d = %s\n", id, reqx, reqy, resx, resy, krespkeylen, print_key (kresp.key, krespkeylen)); } if (simulate && ! kresperr) { char key[HORUS_MAX_KEY_LEN]; size_t key_len; int simx, simy; unsigned long sboffset, snblock; u_int32_t *kht_block_size; int j; assert (reqx == resx && reqy == resy); simx = info->leaf_level; kht_block_size = info->kht_block_size; sboffset = resy * (kht_block_size[resx] / kht_block_size[simx]); snblock = kht_block_size[resx]; if (resx == info->leaf_level) { info->stats.keycalculated = info->stats.success; } else { for (j = 0; j < snblock; j++) { simy = sboffset + j; key_len = sizeof (key); horus_block_key (key, &key_len, simx, simy, kresp.key, krespkeylen, resx, resy, kht_block_size); info->stats.keycalculated++; if (horus_verbose && ! benchmark) printf ("thread[%d]: simulated: K_%d,%d = %s\n", id, simx, simy, print_key (key, key_len)); } } } } if (benchmark) gettimeofday (&end, NULL); close (fd); if (benchmark) { timeval_sub (&end, &start, &res); time = res.tv_sec + res.tv_usec * 0.000001; info->timeval = res; printf ("thread[%d]: %llu/%lu keys in %f secs ( %f q/s\n", id, info->stats.success, nblock, time, info->stats.success/time); if (simulate) printf ("thread[%d]: %llu keys calculated in %f secs ( %f q/s\n", id, info->stats.keycalculated, time, info->stats.keycalculated/time); } else if (horus_verbose) { printf ("thread[%d]: %llu/%lu keys processed.\n", id, info->stats.success, nblock); if (simulate) printf ("thread[%d]: %llu keys calculated\n", id, info->stats.keycalculated); } return NULL; }