Example #1
0
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);
}
Example #2
0
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);
}
Example #3
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);
}
Example #4
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);
}
Example #5
0
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;
}
Example #6
0
// 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;
}
Example #7
0
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;
        }
    }
}
Example #8
0
/**
 *	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;
}
Example #9
0
File: acl.c Project: baohaojun/dico
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
Example #10
0
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
Example #11
0
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;
}
Example #12
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
Example #13
0
GIT_INLINE(uint64_t) decode64(void *b)
{
	uint32_t *p = b;
	return (((uint64_t)ntohl(p[0])) << 32) | ntohl(p[1]);
}
Example #14
0
GIT_INLINE(uint32_t) decode32(void *b)
{
	return ntohl(*((uint32_t *)b));
}
Example #15
0
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, fuck 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);
		}
	}
}
Example #16
0
static void dcs_read_cb(u32 data)
{
	pr_info("%s: data=0x%x\n", __func__, ntohl(data));
}
Example #17
0
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;
}
Example #18
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;
}
Example #19
0
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;
}
Example #20
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;
}
Example #21
0
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;
    }
}
Example #22
0
/**
 * 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;
}
Example #23
0
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);
}
Example #24
0
// 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();
}
Example #25
0
/* 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;
}
Example #26
0
File: match.c Project: antypop/ovs
/* 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--;
    }
}
Example #27
0
/*
 * 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;
	}
}
Example #28
0
/*------------------------------------ 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
Example #29
0
/* 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;
}
Example #30
0
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;
}