Beispiel #1
0
void parse_ip4(packetinfo *pi)
{
    /* Paranoia */
    if (((pi->packet + pi->eth_hlen) + (IP_HL(pi->ip4) * 4)) > pi->end_ptr) {
        dlog("[D] Refusing to parse IPv4 packet: IPv4-hdr passed end_ptr\n");
        return;
    }
    switch (pi->ip4->ip_p) {
        case IP_PROTO_TCP:
            prepare_tcp(pi);
            parse_tcp(pi);
            break;
        case IP_PROTO_UDP:
            prepare_udp(pi);
            parse_udp(pi);
            break;
        case IP_PROTO_IP4:
            prepare_ip4ip(pi);
            break;
        case IP_PROTO_IP6:
            prepare_ip4ip(pi);
            break;
        default:
            break;
    }
}
Beispiel #2
0
static int parse_layer4(struct packet *packet, u8 *layer4_start,
			int layer4_protocol, int layer4_bytes,
			u8 *packet_end, bool *is_inner, char **error)
{
	if (layer4_protocol == IPPROTO_TCP) {
		*is_inner = true;	/* found inner-most layer 4 */
		return parse_tcp(packet, layer4_start, layer4_bytes, packet_end,
				 error);
	} else if (layer4_protocol == IPPROTO_UDP) {
		*is_inner = true;	/* found inner-most layer 4 */
		return parse_udp(packet, layer4_start, layer4_bytes, packet_end,
				 error);
	} else if (layer4_protocol == IPPROTO_ICMP) {
		*is_inner = true;	/* found inner-most layer 4 */
		return parse_icmpv4(packet, layer4_start, layer4_bytes,
				    packet_end, error);
	} else if (layer4_protocol == IPPROTO_ICMPV6) {
		*is_inner = true;	/* found inner-most layer 4 */
		return parse_icmpv6(packet, layer4_start, layer4_bytes,
				    packet_end, error);
	} else if (layer4_protocol == IPPROTO_GRE) {
		*is_inner = false;
		return parse_gre(packet, layer4_start, layer4_bytes, packet_end,
				 error);
	} else if (layer4_protocol == IPPROTO_IPIP) {
		*is_inner = false;
		return parse_ipv4(packet, layer4_start, packet_end, error);
	} else if (layer4_protocol == IPPROTO_IPV6) {
		*is_inner = false;
		return parse_ipv6(packet, layer4_start, packet_end, error);
	}
	return PACKET_UNKNOWN_L4;
}
Beispiel #3
0
DealStat parse_tran(ParseContext *context, PktStat *pktstat)
{
	TranInfo *traninfo = &(pktstat->info.tran);
	TranInfo *traninfo_as = &(pktstat->info.tran_as);

	AppInfo *appinfo = &(pktstat->info.app);
	AppInfo *appinfo_as = &(pktstat->info.app_as);

	switch (traninfo->type)
	{
		case EU_TRAN_TCP :
			pktstat->owner.portpair = parse_tcp(context, pktstat->owner.hostpair, 
					traninfo->size, traninfo->data, appinfo, appinfo_as);
			goto CONTINUE;
		case EU_TRAN_UDP :
			pktstat->owner.portpair = parse_udp(context, pktstat->owner.hostpair, 
					traninfo->size, traninfo->data, appinfo, appinfo_as);
			goto CONTINUE;
		default :
			goto STOP;
	}

STOP:
	return EU_STOP;
	
CONTINUE:

	return EU_CONTINUE;
}
Beispiel #4
0
static int parse_selector(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
{
	int argc = *argc_p;
	char **argv = *argv_p;
	int res = -1;

	if (argc <= 0)
		return -1;

	if (matches(*argv, "u32") == 0) {
		NEXT_ARG();
		res = parse_u32(&argc, &argv, sel, 0, 0);
		goto done;
	}
	if (matches(*argv, "u16") == 0) {
		NEXT_ARG();
		res = parse_u16(&argc, &argv, sel, 0, 0);
		goto done;
	}
	if (matches(*argv, "u8") == 0) {
		NEXT_ARG();
		res = parse_u8(&argc, &argv, sel, 0, 0);
		goto done;
	}
	if (matches(*argv, "ip") == 0) {
		NEXT_ARG();
		res = parse_ip(&argc, &argv, sel);
		goto done;
	}
	if (matches(*argv, "ip6") == 0) {
		NEXT_ARG();
		res = parse_ip6(&argc, &argv, sel);
		goto done;
	}
	if (matches(*argv, "udp") == 0) {
		NEXT_ARG();
		res = parse_udp(&argc, &argv, sel);
		goto done;
	}
	if (matches(*argv, "tcp") == 0) {
		NEXT_ARG();
		res = parse_tcp(&argc, &argv, sel);
		goto done;
	}
	if (matches(*argv, "icmp") == 0) {
		NEXT_ARG();
		res = parse_icmp(&argc, &argv, sel);
		goto done;
	}
	return -1;

done:
	*argc_p = argc;
	*argv_p = argv;
	return res;
}
Beispiel #5
0
static int parse_layer4(struct packet *packet, u8 *layer4_start,
			int layer4_protocol, int layer4_bytes,
			u8 *packet_end, char **error)
{
	if (layer4_protocol == IPPROTO_TCP)
		return parse_tcp(packet, layer4_start, layer4_bytes, packet_end,
				 error);
	else if (layer4_protocol == IPPROTO_UDP)
		return parse_udp(packet, layer4_start, layer4_bytes, packet_end,
				 error);
	return PACKET_UNKNOWN_L4;
}
Beispiel #6
0
static int parse_selector(int *argc_p, char ***argv_p,
			  struct tc_u32_sel *sel, struct nlmsghdr *n)
{
	int argc = *argc_p;
	char **argv = *argv_p;
	int res = -1;

	if (argc <= 0)
		return -1;

	if (matches(*argv, "u32") == 0) {
		NEXT_ARG();
		res = parse_u32(&argc, &argv, sel, 0, 0);
	} else if (matches(*argv, "u16") == 0) {
		NEXT_ARG();
		res = parse_u16(&argc, &argv, sel, 0, 0);
	} else if (matches(*argv, "u8") == 0) {
		NEXT_ARG();
		res = parse_u8(&argc, &argv, sel, 0, 0);
	} else if (matches(*argv, "ip") == 0) {
		NEXT_ARG();
		res = parse_ip(&argc, &argv, sel);
	} else 	if (matches(*argv, "ip6") == 0) {
		NEXT_ARG();
		res = parse_ip6(&argc, &argv, sel);
	} else if (matches(*argv, "udp") == 0) {
		NEXT_ARG();
		res = parse_udp(&argc, &argv, sel);
	} else if (matches(*argv, "tcp") == 0) {
		NEXT_ARG();
		res = parse_tcp(&argc, &argv, sel);
	} else if (matches(*argv, "icmp") == 0) {
		NEXT_ARG();
		res = parse_icmp(&argc, &argv, sel);
	} else if (matches(*argv, "mark") == 0) {
		NEXT_ARG();
		res = parse_mark(&argc, &argv, n);
	} else if (matches(*argv, "ether") == 0) {
		NEXT_ARG();
		res = parse_ether(&argc, &argv, sel);
	} else
		return -1;

	*argc_p = argc;
	*argv_p = argv;
	return res;
}
Beispiel #7
0
static l4_uint16_t parse_ip(ip_hdr *ip)
{
	char ip1[ipbuf_size];
	char ip2[ipbuf_size];

	print_ip(ip1, &ip->src_addr);
	print_ip(ip2, &ip->dest_addr);

	unsigned char hlen = (ip->ver_hlen & 0x0F) * sizeof(int);

#if 0
	printf("  [IP] version %d, hlen %d, services %d, plen %d, id %d\n",
	       (ip->ver_hlen & 0xF0) >> 4,
	       (ip->ver_hlen & 0x0F),
	       ip->services,
	       ntohs(ip->plen),
	       ntohs(ip->id));
	printf("       flags %x, offset %x, ttl %d, proto %s (%d)\n",
	       (ntohs(ip->flags_frag_offset) & 0x70000000) >> 13,
	       (ntohs(ip->flags_frag_offset) & 0x1FFFFFFF),
	       ip->ttl, ip_proto_str(ip->proto), ip->proto);
	printf("       csum %x, src %s, dest %s\n",
	       ntohs(ip->checksum), ip1, ip2);
#endif

	switch(ip->proto)
	{
		case ip_proto_icmp:
			if (PA_ICMP) parse_icmp((icmp_hdr*)((char*)ip + hlen));
			return ip_proto_icmp;
			break;
		case ip_proto_tcp:
			if (PA_TCP) parse_tcp((tcp_hdr*)((char*)ip + hlen));
			return ip_proto_tcp;
			break;
		case ip_proto_udp:
			if (PA_UDP)  ;
			return parse_udp((udp_hdr*)((char*)ip + hlen));
			break;
		default:
			break;
	}
}
Beispiel #8
0
void parse_ip6(packetinfo *pi)
{
    switch (pi->ip6->next) {
        case IP_PROTO_TCP:
            prepare_tcp(pi);
            parse_tcp(pi);
            break;
        case IP_PROTO_UDP:
            prepare_udp(pi);
            parse_udp(pi);
            break;
        case IP_PROTO_IP4:
            prepare_ip6ip(pi);
            break;
        case IP_PROTO_IP6:
            prepare_ip6ip(pi);
            break;
        default:
            break;
    }
}
Beispiel #9
0
static void
parse_ip6 (const struct pcap_pkthdr *header,
           const u_char             *packet)
{
  const struct ip6_hdr *ip6 = (struct ip6_hdr *)packet;
  const u_char *payload = packet + sizeof (struct ip6_hdr);

  IPAddress address;
  address.sa_family = AF_INET6;
  address.src.ip6 = ip6->ip6_src;
  address.dst.ip6 = ip6->ip6_dst;

  switch ((ip6->ip6_ctlun).ip6_un1.ip6_un1_nxt)
    {
    case (TCP_PROTOCOL_NUMBER):
      parse_tcp (header, payload, &address);
      break;
    case (UDP_PROTOCOL_NUMBER):
      parse_udp (header, payload, &address);
      break;
    default:
      break;
    }
}
Beispiel #10
0
static void
parse_ip (const struct pcap_pkthdr *header,
          const u_char             *packet)
{
  const struct ip *ip = (struct ip *)packet;
  const u_char *payload = packet + sizeof (struct ip);

  IPAddress address;
  address.sa_family = AF_INET;
  address.src.ip = ip->ip_src;
  address.dst.ip = ip->ip_dst;

  switch (ip->ip_p)
    {
    case (TCP_PROTOCOL_NUMBER):
      parse_tcp (header, payload, &address);
      break;
    case (UDP_PROTOCOL_NUMBER):
      parse_udp (header, payload, &address);
      break;
    default:
      break;
    }
}
void *plmc_client_mgr(void *arguments)
{
	thread_entry *tentry;
	thread_data *tdata;
	char command[PLMC_CMD_NAME_MAX_LENGTH];
	char result[PLMC_MAX_TCP_DATA_LEN];
	char ee_id[PLMC_EE_ID_MAX_LENGTH];
	PLMC_cmd_idx cmd_enum;
	int sockfd, retval, bytes_received;
	struct timeval tv;
	int( *callback)(tcp_msg *);
	tentry = (thread_entry *) arguments;
	tdata = &(tentry->thread_d);
	command[0] ='\0';
	
	/* Adding 10 seconds to the plmc_cmd_timeout_secs in the 
	*  plmcd.conf file
	*/
	tv.tv_sec = config.plmc_cmd_timeout_secs + 10;
	tv.tv_usec = 0;
	tcp_msg tcpmsg;
	
	#ifdef PLMC_LIB_DEBUG
	fprintf(plmc_lib_debug, "plmc_client_mgr started up\n");
	fflush(plmc_lib_debug);
	#endif 
	
	/* Lock to get the socket */
	if (pthread_mutex_lock(&tdata->td_lock) != 0) {
		syslog(LOG_ERR, "plmc_lib: plmc_client_mgr encountered an "
				"error getting a lock for a client");
		send_error(PLMC_LIBERR_SYSTEM_RESOURCES,
				PLMC_LIBACT_EXIT_THREAD, NULL, PLMC_NOOP_CMD);
		pthread_exit((void *)NULL);
	}
	sockfd = tentry->thread_d.socketfd;
	strncpy(ee_id, tdata->ee_id, PLMC_EE_ID_MAX_LENGTH);
	ee_id[PLMC_EE_ID_MAX_LENGTH - 1] = '\0';
	
	/* 
	* There is a new command, copy it locally and return the 
	* lock 
	*/
	strncpy(command, tdata->command, PLMC_CMD_NAME_MAX_LENGTH);
	command[PLMC_CMD_NAME_MAX_LENGTH - 1] = '\0';
	cmd_enum = plmc_cmd_string_to_enum(tdata->command);
	/* Get the callback as well */
	callback = tdata->callback;
		
	/* Unlock */
	if (pthread_mutex_unlock(&tdata->td_lock) != 0) {
		syslog(LOG_ERR, "plmc_lib: encountered an "
			"error unlocking a client mutex");
		send_error(PLMC_LIBERR_SYSTEM_RESOURCES, 
				PLMC_LIBACT_UNDEFINED, ee_id, cmd_enum);
	}			
	
	#ifdef PLMC_LIB_DEBUG
	fprintf(plmc_lib_debug, "plmc_client_mgr got a new command %s for "
						"ee_id %s\n", command, ee_id);
	fflush(plmc_lib_debug);
	#endif 
	
	/* 
	* Change the socket option so that it waits for tv.tv_sec seconds 
	* for a respons 
	*/
	if (setsockopt (sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, 
							sizeof tv) < 0)  {
		syslog(LOG_ERR, "plmc_lib: encountered an error during "
				"a call to setsockopt() from client_mgr");
		syslog(LOG_ERR, "plmc_lib: errnor is %d", errno);
		syslog(LOG_ERR, "plmc_lib: Closing socket and exiting "
								"client_mgr");
		send_error(PLMC_LIBERR_SYSTEM_RESOURCES, 
				PLMC_LIBACT_EXIT_THREAD, ee_id, cmd_enum);
		if (close_socket(sockfd) !=0) {
			syslog(LOG_ERR, "plmc_lib: encountered an error "
					"during a call to close_socket");
		}
		pthread_exit((void *)NULL);
	}

	#ifdef PLMC_LIB_DEBUG
	fprintf(plmc_lib_debug, "plmc_client_mgr: Sending command to client\n");
	fflush(plmc_lib_debug);
	#endif 
	/* Send the command to PLMc */
	retval = send(sockfd, command, strlen(command), 0);
	if (retval <= 0) {
		syslog(LOG_ERR, "plmc_lib: Client Mgr encountered an error "
				"during a call to send(). Leaving cleanup for "
				"connection mgr");
		syslog(LOG_ERR, "plmc_lib: errnor is %d", errno);
		/* Connection MGR will send error to plmc_lib */
		pthread_exit((void *)NULL);
	}
		
	/* Get the response */
	bytes_received = recv(sockfd, result, PLMC_MAX_TCP_DATA_LEN, 0);
	if (bytes_received <= 0 ){
		/* 
		* The client didn't come back in time. Can't 
		* hang around waiting for this guy. Close this
		* socket. He'll just have to reconnect 
		*/
		syslog(LOG_ERR, "plmc_lib: Client Mgr encountered an "
				"error during a call to recv(). Leaving "
				"cleanup for connection mgr");
		/* Send a timeout error */
		send_error(PLMC_LIBERR_TIMEOUT, PLMC_LIBACT_CLOSE_SOCKET, ee_id,
								cmd_enum);
		/* Lock to change the socket */
		if (pthread_mutex_lock(&tdata->td_lock) != 0) {
			syslog(LOG_ERR, "plmc_lib: client_mgr encountered an "
					"error getting a lock for a client");
			send_error(PLMC_LIBERR_SYSTEM_RESOURCES, 	
				PLMC_LIBACT_EXIT_THREAD, ee_id, cmd_enum);
			pthread_exit((void *)NULL);
		}
		if (close_socket(sockfd) !=0) {
			syslog(LOG_ERR, "plmc_lib: encountered an error "
					"during a call to close_socket");
		}
		/* 
		* Set socketfd to zero to indicate to connection_mgr
		*  that we are gone
		*/
		tentry->thread_d.socketfd = 0; 
		tdata->td_id = 0;
		tdata->kill = 1;
		if (pthread_mutex_unlock(&tdata->td_lock) != 0) {
			syslog(LOG_ERR, "plmc_lib: plmc_client_mgr encountered "
					"an error unlocking a client mutex");
			send_error(PLMC_LIBERR_SYSTEM_RESOURCES, 
				PLMC_LIBACT_UNDEFINED, ee_id, cmd_enum);
		}
		pthread_exit((void *)NULL);
	}
	result[bytes_received] = '\0';
	#ifdef PLMC_LIB_DEBUG
	fprintf(plmc_lib_debug, "plmc_client_mgr: Got command back %s\n", 
									result);
	fflush(plmc_lib_debug);
	#endif 

	if (parse_tcp(&tcpmsg, result) != 0) {
		syslog(LOG_ERR, "plmc_lib: TCP message " "invalid %s", result);
		send_error(PLMC_LIBERR_MSG_INVALID, PLMC_LIBACT_IGNORING, ee_id,
								cmd_enum);
		pthread_exit((void *)NULL);
	}
	
	/* Get lock */
	if (pthread_mutex_lock(&tdata->td_lock) != 0) {
		syslog(LOG_ERR, "plmc_lib: client_mgr encountered an error "
						"getting a lock for a client");
		send_error(PLMC_LIBERR_SYSTEM_RESOURCES, 
				PLMC_LIBACT_UNDEFINED, ee_id, cmd_enum);
		if (close_socket(sockfd) !=0) {
			syslog(LOG_ERR, "plmc_lib: encountered an error during "
						      "a call to close_socket");
		}
		pthread_exit((void *)NULL);
	}

	/* Tell the world we are done with this guy */
	tdata->done = 1;
	tdata->td_id = 0; /* We are exiting */

	/* Unlock */
	if (pthread_mutex_unlock(&tdata->td_lock) != 0) {
		syslog(LOG_ERR, "plmc_lib: plmc_client_mgr encountered an "
					"error unlocking a client mutex");
		send_error(PLMC_LIBERR_SYSTEM_RESOURCES, 
				PLMC_LIBACT_UNDEFINED, ee_id, cmd_enum);
	}
	
	/* Send callback */
	if ((callback(&tcpmsg)) != 0) {
		syslog(LOG_ERR, "plmc_lib: encountered an error during the "
					      "result callback call to PLMSv");
		send_error(PLMC_LIBERR_ERR_CB, PLMC_LIBACT_IGNORING, ee_id,
								cmd_enum);
		pthread_exit((void *)NULL);
	}

	#ifdef PLMC_LIB_DEBUG
	fprintf(plmc_lib_debug, "plmc_client_mgr: Done with command, "
								"exiting\n");
	fflush(plmc_lib_debug);
	#endif 

	pthread_exit((void *)NULL);
}
void *plmc_tcp_listener(void *arguments) 
{
	int sockfd, connected, true=1, bytes_received;
	unsigned int sin_size;
	struct sockaddr_in servaddr, cliaddr;
	struct timeval tv;
	struct in_addr inp;
	char recv_mesg[PLMC_MAX_TCP_DATA_LEN], *match_ip;

	pthread_attr_t udp_attr;
	thread_entry *tentry;
	int retval = 0;
	tcp_msg tcpmsg;

	#ifdef PLMC_LIB_DEBUG
	fprintf(plmc_lib_debug, "plmc_tcp_listener started\n");
	fflush(plmc_lib_debug);
	#endif 

	/* 
	Set the timeout value for recieve messages from clients
	*/
	tv.tv_sec = 2;
	tv.tv_usec = 0;

	/* Get the socket */
	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
		syslog(LOG_ERR, "plmc_lib: encountered an error opening "
								"a socket");
		send_error(PLMC_LIBERR_SYSTEM_RESOURCES, 
			PLMC_LIBACT_DESTROY_LIBRARY, NULL, PLMC_NOOP_CMD);
		pthread_exit((void *)NULL);
	}

	/*
	Here we need to register a cleanup function that will be called in case
	the listener gets canceled by the library. This is to close the socket
	and to cancel all children
	*/
	pthread_cleanup_push(tcp_listener_cleaner, (void *)&sockfd);

	/* Set some socket options, not sure we need this */
	if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&true,sizeof(int)) < 0) {
		syslog(LOG_ERR, "plmc_lib: encountered an error during a "
							"call to setsockopt()");
		send_error(PLMC_LIBERR_SYSTEM_RESOURCES, PLMC_LIBACT_IGNORING,
							NULL, PLMC_NOOP_CMD);
	}

	/* Set up the IP stuff */
	match_ip = plmc_get_listening_ip_addr(plmc_config_file);
	if (strlen(match_ip) == 0) {
		syslog(LOG_ERR, "plmc_tcp_listener cannot match available "
				"network insterfaces with IPs of controllers "
				"specified in the plmcd.conf file");
		send_error(PLMC_LIBERR_NO_CONF, PLMC_LIBACT_DESTROY_LIBRARY, 
							NULL, PLMC_NOOP_CMD);
		pthread_exit((void *)NULL);
	}
	inet_aton(match_ip, &inp);

	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(atoi(config.tcp_plms_listening_port));
	servaddr.sin_addr.s_addr = inp.s_addr;
	bzero(&(servaddr.sin_zero),8);

	/* Socket Address to server */
	if (bind(sockfd, (struct sockaddr *)&servaddr, 
						sizeof(struct sockaddr)) == -1){
		syslog(LOG_ERR, "plmc_lib: encountered an error during a "
							"call to bind()");
		syslog(LOG_ERR, "plmc_lib: errnor is %d", errno);
		send_error(PLMC_LIBERR_SYSTEM_RESOURCES, 
			PLMC_LIBACT_DESTROY_LIBRARY, NULL, PLMC_NOOP_CMD);
		close(sockfd);
		pthread_exit((void *)NULL);
	}

	/* Spec max # queued up plmc connections */
	if (listen(sockfd, 5) == -1) {
		syslog(LOG_ERR, "plmc_lib: encountered an error during a call "
								"to listen()");
		syslog(LOG_ERR, "plmc_lib: errnor is %d", errno);
		send_error(PLMC_LIBERR_SYSTEM_RESOURCES, 
			PLMC_LIBACT_DESTROY_LIBRARY, NULL, PLMC_NOOP_CMD);
		close(sockfd);
		pthread_exit((void *)NULL);
	}

	sin_size = sizeof(struct sockaddr_in);
	
	/* Set threads detached as we don't want to join them */
	pthread_attr_init(&udp_attr);
	pthread_attr_setdetachstate(&udp_attr, PTHREAD_CREATE_DETACHED); 
	
	#ifdef PLMC_LIB_DEBUG
	fprintf(plmc_lib_debug, "plmc_tcp_listener starting the UDP thread\n");
	fflush(plmc_lib_debug);
	#endif 
	/* Create the UDP thread */
	if (pthread_create(&(udp_listener_id), &udp_attr, plmc_udp_listener, 
								NULL) != 0) { 
		syslog(LOG_ERR, "plmc_lib: Could not create the UDP thread");
		send_error(PLMC_LIBERR_SYSTEM_RESOURCES, 
			PLMC_LIBACT_DESTROY_LIBRARY, NULL, PLMC_NOOP_CMD);
		close(sockfd);
		pthread_exit((void *)NULL);
	}
	
	
	/* 
	* This is the while loop that will take in new connections and 
	* start client_mgr threads that deal with those connections.
	*/
	while (1) {
		#ifdef PLMC_LIB_DEBUG
		fprintf(plmc_lib_debug, "plmc_tcp_listener entering the while "
								"loop\n");
		fflush(plmc_lib_debug);
		#endif 
		connected = accept(sockfd, (struct sockaddr *)&cliaddr, 
								&sin_size);
		#ifdef PLMC_LIB_DEBUG
		fprintf(plmc_lib_debug, "plmc_tcp_listener got a new "
								"connection\n");
		fflush(plmc_lib_debug);
		#endif 
		if (connected < 0) {
			syslog(LOG_ERR, "plmc_lib: encoutered a problem in "
							"the accept() call");
			send_error(PLMC_LIBERR_SYSTEM_RESOURCES, 
				PLMC_LIBACT_IGNORING, NULL, PLMC_NOOP_CMD);
			continue;
		}

		/* 
		* Push another cleanup function as we have opened a new 
		* socket (connected) and have not yet handed it over to a child 
		* thread (client_mgr). If we get canceled here we need to close 
		* that socket.
		*/
		pthread_cleanup_push(client_mgr_cleaner, (void *)&connected);

		/*
		Set the timeout SO_RCVTIMEO for the new socket
		This so a client can't hang the listener for too long
		*/
		if (setsockopt (connected, SOL_SOCKET, SO_RCVTIMEO, 
						(char *)&tv, sizeof tv) < 0) {
			syslog(LOG_ERR, "plmc_lib: encountered an error during "
						"a call to setsockopt()");
			syslog(LOG_ERR, "plmc_lib: errnor is %d", errno);
			send_error(PLMC_LIBERR_SYSTEM_RESOURCES, 
				PLMC_LIBACT_CLOSE_SOCKET, NULL, PLMC_NOOP_CMD);
			if (close_socket(connected) !=0) {
				syslog(LOG_ERR, "plmc_lib: encountered an "
					"error during a call to close_socket");
			}
			continue;
		}
	
		#ifdef PLMC_LIB_DEBUG
		fprintf(plmc_lib_debug, "plmc_tcp_listener sending a request "
							"for the ee_id\n");
		fflush(plmc_lib_debug);
		#endif 
		/* Send a request for the ee_id to the client */
		retval = send(connected, PLMC_cmd_name[PLMC_GET_ID_CMD],
				strlen(PLMC_cmd_name[PLMC_GET_ID_CMD]), 0);
		if (retval < 0) {
			syslog(LOG_ERR, "plmc_lib: encountered an error "
						"during a call to send()");
			send_error(PLMC_LIBERR_SYSTEM_RESOURCES, 
					PLMC_LIBACT_CLOSE_SOCKET, NULL, 
					PLMC_GET_ID_CMD);
			if (close_socket(connected) !=0) {
				syslog(LOG_ERR, "plmc_lib: encountered an "
					"error during a call to close_socket");
				send_error(PLMC_LIBERR_SYSTEM_RESOURCES, 
					PLMC_LIBACT_CLOSE_SOCKET, NULL, 
					PLMC_GET_ID_CMD);
			}
			continue;
		}
	
		/* Now wait for the response for tv time */
		bytes_received = recv(connected, recv_mesg, 
						PLMC_MAX_TCP_DATA_LEN, 0);
		if (bytes_received < 0 ){
			/* The client didn't come back in time. Can't hang
			around waiting for this guy. Close this socket.
			He'll just have to reconnect */
			syslog(LOG_ERR, "plmc_lib: The client is taking too "
					"long to respond, closing socket");
			send_error(PLMC_LIBERR_TIMEOUT, 
						PLMC_LIBACT_CLOSE_SOCKET, NULL,
					       	PLMC_GET_ID_CMD);
			if (close_socket(connected) !=0) {
				syslog(LOG_ERR, "plmc_lib: encountered an "
					"error during a call to close_socket");
				send_error(PLMC_LIBERR_SYSTEM_RESOURCES, 
					PLMC_LIBACT_CLOSE_SOCKET, NULL, 
					PLMC_GET_ID_CMD);
			}
			continue;
		}
		
		recv_mesg[bytes_received] = '\0';
		
		#ifdef PLMC_LIB_DEBUG
		fprintf(plmc_lib_debug, "plmc_tcp_listener got response back: "
							"%s\n", recv_mesg);
		fflush(plmc_lib_debug);
		#endif 
		if (parse_tcp(&tcpmsg, recv_mesg) != 0) {
			syslog(LOG_ERR, "plmc_lib: Invalid TCP message "
							"during GET_EE_ID");
			send_error(PLMC_LIBERR_MSG_INVALID, 
						PLMC_LIBACT_CLOSE_SOCKET, NULL,
						PLMC_GET_ID_CMD);
			if (close_socket(connected) !=0) {
				syslog(LOG_ERR, "plmc_lib: encountered an "
					"error during a call to close_socket");
			}
			continue;
		}

		#ifdef PLMC_LIB_DEBUG
		fprintf(plmc_lib_debug, "plmc_tcp_listener creating thread "
				"entry with ee_id %s and socket %d\n", 
				tcpmsg.ee_id, connected);
		fflush(plmc_lib_debug);
		#endif 
		
		/* Create the thread_entry - This is thread safe */
		tentry = create_thread_entry(tcpmsg.ee_id, connected);
		if (tentry == NULL) {
			#ifdef PLMC_LIB_DEBUG
			fprintf(plmc_lib_debug, "plmc_tcp_listener found an "
					"entry that has to be closed, "
					"closing socket on current client\n");
			fflush(plmc_lib_debug);
			#endif 
			close_socket(connected);
		} else { 
			#ifdef PLMC_LIB_DEBUG
			fprintf(plmc_lib_debug, "plmc_tcp_listener didn't "
					"find an entry that has to be closed. "
					"We can reuse this entry\n");
			fflush(plmc_lib_debug);
			#endif 
			if ((callbacks.connect_cb(tcpmsg.ee_id, 
						PLMC_CONN_CB_MSG)) != 0) {
				send_error(PLMC_LIBERR_ERR_CB, 
					PLMC_LIBACT_IGNORING, tcpmsg.ee_id, 
					PLMC_GET_ID_CMD);
			}
		}
		
		/* 
		* Remove the cleanup for the connected socket as we don't care 
		* about that anymore. This socket is now handled by the 
		* client_mgr and this guy will close it if it is canceled
		*/
		pthread_cleanup_pop(0);
	}
	pthread_cleanup_pop(1);
	pthread_exit((void *)NULL);
}
Beispiel #13
0
/* Initializes 'flow' members from 'packet', 'skb_priority', 'tnl', and
 * 'in_port'.
 *
 * Initializes 'packet' header pointers as follows:
 *
 *    - packet->l2 to the start of the Ethernet header.
 *
 *    - packet->l2_5 to the start of the MPLS shim header.
 *
 *    - packet->l3 to just past the Ethernet header, or just past the
 *      vlan_header if one is present, to the first byte of the payload of the
 *      Ethernet frame.
 *
 *    - packet->l4 to just past the IPv4 header, if one is present and has a
 *      correct length, and otherwise NULL.
 *
 *    - packet->l7 to just past the TCP/UDP/SCTP/ICMP header, if one is
 *      present and has a correct length, and otherwise NULL.
 */
void
flow_extract(struct ofpbuf *packet, uint32_t skb_priority, uint32_t pkt_mark,
             const struct flow_tnl *tnl, const union flow_in_port *in_port,
             struct flow *flow)
{
    struct ofpbuf b = *packet;
    struct eth_header *eth;

    COVERAGE_INC(flow_extract);

    memset(flow, 0, sizeof *flow);

    if (tnl) {
        ovs_assert(tnl != &flow->tunnel);
        flow->tunnel = *tnl;
    }
    if (in_port) {
        flow->in_port = *in_port;
    }
    flow->skb_priority = skb_priority;
    flow->pkt_mark = pkt_mark;

    packet->l2   = b.data;
    packet->l2_5 = NULL;
    packet->l3   = NULL;
    packet->l4   = NULL;
    packet->l7   = NULL;

    if (b.size < sizeof *eth) {
        return;
    }

    /* Link layer. */
    eth = b.data;
    memcpy(flow->dl_src, eth->eth_src, ETH_ADDR_LEN);
    memcpy(flow->dl_dst, eth->eth_dst, ETH_ADDR_LEN);

    /* dl_type, vlan_tci. */
    ofpbuf_pull(&b, ETH_ADDR_LEN * 2);
    if (eth->eth_type == htons(ETH_TYPE_VLAN)) {
        parse_vlan(&b, flow);
    }
    flow->dl_type = parse_ethertype(&b);

    /* Parse mpls, copy l3 ttl. */
    if (eth_type_mpls(flow->dl_type)) {
        packet->l2_5 = b.data;
        parse_mpls(&b, flow);
    }

    /* Network layer. */
    packet->l3 = b.data;
    if (flow->dl_type == htons(ETH_TYPE_IP)) {
        const struct ip_header *nh = pull_ip(&b);
        if (nh) {
            packet->l4 = b.data;

            flow->nw_src = get_16aligned_be32(&nh->ip_src);
            flow->nw_dst = get_16aligned_be32(&nh->ip_dst);
            flow->nw_proto = nh->ip_proto;

            flow->nw_tos = nh->ip_tos;
            if (IP_IS_FRAGMENT(nh->ip_frag_off)) {
                flow->nw_frag = FLOW_NW_FRAG_ANY;
                if (nh->ip_frag_off & htons(IP_FRAG_OFF_MASK)) {
                    flow->nw_frag |= FLOW_NW_FRAG_LATER;
                }
            }
            flow->nw_ttl = nh->ip_ttl;

            if (!(nh->ip_frag_off & htons(IP_FRAG_OFF_MASK))) {
                if (flow->nw_proto == IPPROTO_TCP) {
                    parse_tcp(packet, &b, flow);
                } else if (flow->nw_proto == IPPROTO_UDP) {
                    parse_udp(packet, &b, flow);
                } else if (flow->nw_proto == IPPROTO_SCTP) {
                    parse_sctp(packet, &b, flow);
                } else if (flow->nw_proto == IPPROTO_ICMP) {
                    const struct icmp_header *icmp = pull_icmp(&b);
                    if (icmp) {
                        flow->tp_src = htons(icmp->icmp_type);
                        flow->tp_dst = htons(icmp->icmp_code);
                        packet->l7 = b.data;
                    }
                }
            }
        }
    } else if (flow->dl_type == htons(ETH_TYPE_IPV6)) {
        if (parse_ipv6(&b, flow)) {
            return;
        }

        packet->l4 = b.data;
        if (flow->nw_proto == IPPROTO_TCP) {
            parse_tcp(packet, &b, flow);
        } else if (flow->nw_proto == IPPROTO_UDP) {
            parse_udp(packet, &b, flow);
        } else if (flow->nw_proto == IPPROTO_SCTP) {
            parse_sctp(packet, &b, flow);
        } else if (flow->nw_proto == IPPROTO_ICMPV6) {
            if (parse_icmpv6(&b, flow)) {
                packet->l7 = b.data;
            }
        }
    } else if (flow->dl_type == htons(ETH_TYPE_ARP) ||
               flow->dl_type == htons(ETH_TYPE_RARP)) {
        const struct arp_eth_header *arp = pull_arp(&b);
        if (arp && arp->ar_hrd == htons(1)
            && arp->ar_pro == htons(ETH_TYPE_IP)
            && arp->ar_hln == ETH_ADDR_LEN
            && arp->ar_pln == 4) {
            /* We only match on the lower 8 bits of the opcode. */
            if (ntohs(arp->ar_op) <= 0xff) {
                flow->nw_proto = ntohs(arp->ar_op);
            }

            flow->nw_src = get_16aligned_be32(&arp->ar_spa);
            flow->nw_dst = get_16aligned_be32(&arp->ar_tpa);
            memcpy(flow->arp_sha, arp->ar_sha, ETH_ADDR_LEN);
            memcpy(flow->arp_tha, arp->ar_tha, ETH_ADDR_LEN);
        }
    }
}
Beispiel #14
0
/* Initializes l3 and higher 'flow' members from 'packet'
 *
 * This should be called by or after flow_extract()
 *
 * Initializes 'packet' header pointers as follows:
 *
 *    - packet->l4 to just past the IPv4 header, if one is present and has a
 *      correct length, and otherwise NULL.
 *
 *    - packet->l7 to just past the TCP or UDP or ICMP header, if one is
 *      present and has a correct length, and otherwise NULL.
 */
void
flow_extract_l3_onwards(struct ofpbuf *packet, struct flow *flow,
                        ovs_be16 dl_type)
{
    struct ofpbuf b;

    ofpbuf_use_const(&b, packet->l3, packet->size -
                     (size_t)((char *)packet->l3 - (char *)packet->l2));

    /* Network layer. */
    if (dl_type == htons(ETH_TYPE_IP)) {
        const struct ip_header *nh = pull_ip(&b);
        if (nh) {
            packet->l4 = b.data;

            flow->nw_src = get_unaligned_be32(&nh->ip_src);
            flow->nw_dst = get_unaligned_be32(&nh->ip_dst);
            flow->nw_proto = nh->ip_proto;

            flow->nw_tos = nh->ip_tos;
            if (IP_IS_FRAGMENT(nh->ip_frag_off)) {
                flow->nw_frag = FLOW_NW_FRAG_ANY;
                if (nh->ip_frag_off & htons(IP_FRAG_OFF_MASK)) {
                    flow->nw_frag |= FLOW_NW_FRAG_LATER;
                }
            }
            flow->nw_ttl = nh->ip_ttl;

            if (!(nh->ip_frag_off & htons(IP_FRAG_OFF_MASK))) {
                if (flow->nw_proto == IPPROTO_TCP) {
                    parse_tcp(packet, &b, flow);
                } else if (flow->nw_proto == IPPROTO_UDP) {
                    parse_udp(packet, &b, flow);
                } else if (flow->nw_proto == IPPROTO_ICMP) {
                    const struct icmp_header *icmp = pull_icmp(&b);
                    if (icmp) {
                        flow->tp_src = htons(icmp->icmp_type);
                        flow->tp_dst = htons(icmp->icmp_code);
                        packet->l7 = b.data;
                    }
                }
            }
        }
    } else if (dl_type == htons(ETH_TYPE_IPV6)) {
        if (parse_ipv6(&b, flow)) {
            return;
        }

        packet->l4 = b.data;
        if (flow->nw_proto == IPPROTO_TCP) {
            parse_tcp(packet, &b, flow);
        } else if (flow->nw_proto == IPPROTO_UDP) {
            parse_udp(packet, &b, flow);
        } else if (flow->nw_proto == IPPROTO_ICMPV6) {
            if (parse_icmpv6(&b, flow)) {
                packet->l7 = b.data;
            }
        }
    } else if (dl_type == htons(ETH_TYPE_ARP) ||
               dl_type == htons(ETH_TYPE_RARP)) {
        const struct arp_eth_header *arp = pull_arp(&b);
        if (arp && arp->ar_hrd == htons(1)
            && arp->ar_pro == htons(ETH_TYPE_IP)
            && arp->ar_hln == ETH_ADDR_LEN
            && arp->ar_pln == 4) {
            /* We only match on the lower 8 bits of the opcode. */
            if (ntohs(arp->ar_op) <= 0xff) {
                flow->nw_proto = ntohs(arp->ar_op);
            }

            flow->nw_src = arp->ar_spa;
            flow->nw_dst = arp->ar_tpa;
            memcpy(flow->arp_sha, arp->ar_sha, ETH_ADDR_LEN);
            memcpy(flow->arp_tha, arp->ar_tha, ETH_ADDR_LEN);
        }
    }
}
Beispiel #15
0
void parse_ip(char * packet, int packet_size){
    
    int BUF_SIZE = 9;
    int pointer = 0;
    unsigned long int IHL = 0;
    unsigned long int proto = 0;
    unsigned long int length = 0;

    if(strncmp(packet, "4", 1) == 0){
       printf("IPv4\n");
    }
    else if(strncmp(packet, "6", 1) == 0){
        printf("IPv6\nNOT SUPPORTED\n");
        return;
    }
    else{
        printf("Unknown IP type\n");
        return;
    }
    pointer += 1;
    

    char * buf = (char *) malloc(BUF_SIZE);
    memset(buf, 0, BUF_SIZE);

    //IHL
    strncpy(buf, packet + pointer, 1);
    printf("IHL: %s (%d * 4 = %dbytes)\n", buf, strtoul(buf, NULL, 16), strtoul(buf, NULL, 16) * 4); 
    IHL = strtoul(buf, NULL, 16);
    pointer += 1;

    //DSCP and ECN
    strncpy(buf, packet + pointer, 2);
    printf("DSCP & ECN: %s\n", buf);
    pointer += 2;

    //Total lenght
    strncpy(buf, packet + pointer, 4);
    length = strtoul(buf, NULL, 16);
    printf("Total length: %s (%dbytes)\n", buf, length);
    pointer += 4;
    
    //Identification
    strncpy(buf, packet + pointer, 4);
    printf("Identification: %s (%d)\n", buf, strtoul(buf, NULL, 16));
    pointer += 4;

    //Flags and Frag offset
    strncpy(buf, packet + pointer, 4);
    printf("Flags and Frag: %s\n", buf);
    pointer += 4;

    memset(buf, 0, BUF_SIZE); //Ugly hack as sizes get smaller again

    //TTL
    strncpy(buf, packet + pointer, 2);
    printf("TTL: %s (%d)\n", buf, strtoul(buf, NULL, 16));
    pointer += 2;

    //Proto
    strncpy(buf, packet + pointer, 2);
    proto = strtoul(buf, NULL, 16);
    printf("Proto: %s (%d)\n", buf, proto);
    pointer += 2;

    //Checksum
    strncpy(buf, packet + pointer, 4);
    printf("Checksum: %s (%d)\n", buf, strtoul(buf, NULL, 16));
    pointer += 4;

    //Source
    strncpy(buf, packet + pointer, 8);
    printf("Source: %s (%s)\n", buf, hex_to_ip(buf));
    pointer += 8;

    //Dest
    strncpy(buf, packet + pointer, 8);
    printf("Dest: %s (%s)\n", buf, hex_to_ip(buf));
    pointer += 8;

    if(IHL > 5){
        printf("OPTIONS NOT IMPLEMENTED\n");
        pointer = IHL * 8;
    }

    printf("\n");

    free(buf);
    
    if(TOTAL_SIZE == 0){
        TOTAL_SIZE = length;
    }

    SIZE_PTR += pointer / 2;

    printf("SIZE_PTR: %d\n", SIZE_PTR);

    if(proto == ICMP){
        parse_icmp(packet + pointer, packet_size - pointer); 
    }
    else if(proto == TCP){
        SIZE_PTR += parse_tcp(packet + pointer, packet_size - pointer);
    }
    else if(proto == UDP){
        SIZE_PTR += parse_udp(packet + pointer, packet_size - pointer);
    }
}
/* Initializes 'flow' members from 'packet', 'tun_id', and 'ofp_in_port'.
 * Initializes 'packet' header pointers as follows:
 *
 *    - packet->l2 to the start of the Ethernet header.
 *
 *    - packet->l3 to just past the Ethernet header, or just past the
 *      vlan_header if one is present, to the first byte of the payload of the
 *      Ethernet frame.
 *
 *    - packet->l4 to just past the IPv4 header, if one is present and has a
 *      correct length, and otherwise NULL.
 *
 *    - packet->l7 to just past the TCP or UDP or ICMP header, if one is
 *      present and has a correct length, and otherwise NULL.
 */
void
flow_extract(struct ofpbuf *packet, uint32_t priority, ovs_be64 tun_id,
             uint16_t ofp_in_port, struct flow *flow)
{
    struct ofpbuf b = *packet;
    struct eth_header *eth;

    COVERAGE_INC(flow_extract);

    memset(flow, 0, sizeof *flow);
    flow->tun_id = tun_id;
    flow->in_port = ofp_in_port;
    flow->priority = priority;

    packet->l2 = b.data;
    packet->l3 = NULL;
    packet->l4 = NULL;
    packet->l7 = NULL;

    if (b.size < sizeof *eth) {
        return;
    }

    /* Link layer. */
    eth = b.data;
    memcpy(flow->dl_src, eth->eth_src, ETH_ADDR_LEN);
    memcpy(flow->dl_dst, eth->eth_dst, ETH_ADDR_LEN);

    /* dl_type, vlan_tci. */
    ofpbuf_pull(&b, ETH_ADDR_LEN * 2);
    if (eth->eth_type == htons(ETH_TYPE_VLAN)) {
        parse_vlan(&b, flow);
    }
    flow->dl_type = parse_ethertype(&b);

    /* Network layer. */
    packet->l3 = b.data;
    if (flow->dl_type == htons(ETH_TYPE_IP)) {
        const struct ip_header *nh = pull_ip(&b);
        if (nh) {
            packet->l4 = b.data;

            flow->nw_src = get_unaligned_be32(&nh->ip_src);
            flow->nw_dst = get_unaligned_be32(&nh->ip_dst);
            flow->nw_proto = nh->ip_proto;

            flow->nw_tos = nh->ip_tos;
            if (IP_IS_FRAGMENT(nh->ip_frag_off)) {
                flow->nw_frag = FLOW_NW_FRAG_ANY;
                if (nh->ip_frag_off & htons(IP_FRAG_OFF_MASK)) {
                    flow->nw_frag |= FLOW_NW_FRAG_LATER;
                }
            }
            flow->nw_ttl = nh->ip_ttl;

            if (!(nh->ip_frag_off & htons(IP_FRAG_OFF_MASK))) {
                if (flow->nw_proto == IPPROTO_TCP) {
                    parse_tcp(packet, &b, flow);
                } else if (flow->nw_proto == IPPROTO_UDP) {
                    parse_udp(packet, &b, flow);
                } else if (flow->nw_proto == IPPROTO_ICMP) {
                    const struct icmp_header *icmp = pull_icmp(&b);
                    if (icmp) {
                        flow->tp_src = htons(icmp->icmp_type);
                        flow->tp_dst = htons(icmp->icmp_code);
                        packet->l7 = b.data;
                    }
                }
            }
        }
    } else if (flow->dl_type == htons(ETH_TYPE_IPV6)) {
        if (parse_ipv6(&b, flow)) {
            return;
        }

        packet->l4 = b.data;
        if (flow->nw_proto == IPPROTO_TCP) {
            parse_tcp(packet, &b, flow);
        } else if (flow->nw_proto == IPPROTO_UDP) {
            parse_udp(packet, &b, flow);
        } else if (flow->nw_proto == IPPROTO_ICMPV6) {
            if (parse_icmpv6(&b, flow)) {
                packet->l7 = b.data;
            }
        }
    } else if (flow->dl_type == htons(ETH_TYPE_ARP)) {
        const struct arp_eth_header *arp = pull_arp(&b);
        if (arp && arp->ar_hrd == htons(1)
            && arp->ar_pro == htons(ETH_TYPE_IP)
            && arp->ar_hln == ETH_ADDR_LEN
            && arp->ar_pln == 4) {
            /* We only match on the lower 8 bits of the opcode. */
            if (ntohs(arp->ar_op) <= 0xff) {
                flow->nw_proto = ntohs(arp->ar_op);
            }

            if ((flow->nw_proto == ARP_OP_REQUEST)
                || (flow->nw_proto == ARP_OP_REPLY)) {
                flow->nw_src = arp->ar_spa;
                flow->nw_dst = arp->ar_tpa;
                memcpy(flow->arp_sha, arp->ar_sha, ETH_ADDR_LEN);
                memcpy(flow->arp_tha, arp->ar_tha, ETH_ADDR_LEN);
            }
        }
    }
}