Ejemplo n.º 1
0
// Returns IPv6 address first, then IPv4
static struct addrinfo *
searchBest(struct addrinfo *res) {
	struct addrinfo *pt;

	for (pt=res; pt; pt=pt->ai_next) {
		char tmp[100];
		rtl_trace (5, "best : '%s' '%s'\n", get_ip_fam(pt->ai_addr), get_ip_str(pt->ai_addr, tmp, sizeof(tmp)));
		if	(pt->ai_family == AF_INET6)
			return pt;
	}
	return res;
}
Ejemplo n.º 2
0
int		get_pasv(t_info *info)
{
  t_rep		rep;
  char		*ip_str;
  char		ip[16];
  unsigned int	port;

  memset(ip, 0, sizeof(ip));
  if (!send_cmd(info, "PASV", NULL) || !get_answer(info, &rep))
    return (0);
  if (!(ip_str = get_ip_str(rep.msg)))
    return (0);
  get_ip_value(ip_str, ip);
  port = get_port_value(ip_str);
  return (create_dtp(info, ip, port));
}
Ejemplo n.º 3
0
void one_job(int lpnumber)
{
	int lp, open_sleep = 10;
	struct sockaddr_storage client;
	socklen_t clientlen = sizeof(client);

	if (getpeername(0, (struct sockaddr *)&client, &clientlen) >= 0) {
		char host[INET6_ADDRSTRLEN];
		dolog(LOG_NOTICE, "Connection from %s port %hu\n", get_ip_str((struct sockaddr *)&client, host, sizeof(host)), get_port((struct sockaddr *)&client));
	}
	if (get_lock(lpnumber) == 0)
		return;
	/* Make sure lp device is open... */
	while ((lp = open_printer(lpnumber)) == -1) {
		sleep(open_sleep);
		if (open_sleep < 320) /* ~5 min interval to avoid spam in syslog */
			open_sleep *= 2;
	}
	if (copy_stream(0, lp) < 0)
		dolog(LOGOPTS, "copy_stream: %m\n");
	close(lp);
	free_lock();
}
Ejemplo n.º 4
0
Archivo: lsif.c Proyecto: Slixbits/lsif
int main(int argc, char **argv)
{
  char            buf[8192] = {0};
  struct ifconf   ifc = {0};
  struct ifreq   *ifr = NULL;
  int             sck = 0;
  int             nInterfaces = 0;
  int             i = 0;
  char            ip[INET6_ADDRSTRLEN] = {0};
  struct ifreq    *item;
  struct sockaddr *addr;
  socklen_t       salen;
  char            hostname[NI_MAXHOST];
  struct ifreq    *flagsStruct;
  char            *ignoreLoopbackFlag = "--ignoreloopback";
  int             ignoreLoopback = 0;
  int             argIndex = 1;

  /* Process command-line arguments. */
  for(; argIndex < argc; argIndex++) {
    if(strcmp(argv[argIndex], ignoreLoopbackFlag) == 0)
        ignoreLoopback = 1;
    else {
        fprintf(stderr, "Invalid argument (%s)\n", argv[argIndex]);
		return 1;
    }
  }


  /* Get a socket handle. */
  sck = socket(PF_INET, SOCK_DGRAM, 0);
  if(sck < 0) {
    fatal_perror("socket");
    return 1;
  }
 
  /* Query available interfaces. */
  ifc.ifc_len = sizeof(buf);
  ifc.ifc_buf = buf;
  if(ioctl(sck, SIOCGIFCONF, &ifc) < 0) {
    fatal_perror("ioctl(SIOCGIFCONF)");
    return 1;
  }
  /* Iterate through the list of interfaces. */
  ifr = ifc.ifc_req;
  nInterfaces = ifc.ifc_len / sizeof(struct ifreq); 
  for(i = 0; i < nInterfaces; i++) {
    bzero(hostname, NI_MAXHOST);
    item = &ifr[i];

	if(get_flags(sck, flagsStruct))
		return 1;

    /* Check if this is a loopback adapter and skip it if requested. */
    if(ignoreLoopback && ((flagsStruct->ifr_flags & IFF_LOOPBACK) != 0)) {
        free(flagsStruct);
        continue;
    }
    
    /* Show the device name and IP address */
    addr = &(item->ifr_addr);

    switch(addr->sa_family) {
    case AF_INET:
      salen = sizeof(struct sockaddr_in);
      break;
    case AF_INET6:
      salen = sizeof(struct sockaddr_in6);
      break;
    default:
      salen = 0;
    }
   
    /* the call to get the mac address changes what is stored in the
       item, meaning that we need to determine the hostname now */
    getnameinfo(addr, salen, hostname, sizeof(hostname), NULL, 0, NI_NAMEREQD);


    /* Get the address 
     * This may seem silly but it seems to be needed on some systems 
     */
    if(ioctl(sck, SIOCGIFADDR, item) < 0) {
      fatal_perror("ioctl(OSIOCGIFADDR)");
    }
    printf("%s %s",
       item->ifr_name,
       get_ip_str(addr, ip, INET6_ADDRSTRLEN));
    
    /* Lots of different ways to get the ethernet address */
#ifdef SIOCGIFHWADDR
    /* Linux */
    /* Get the MAC address */
    if(ioctl(sck, SIOCGIFHWADDR, item) < 0) {
      fatal_perror("ioctl(SIOCGIFHWADDR)");
      return 1;
    }
    
    /* display result */
    printf(" %02x:%02x:%02x:%02x:%02x:%02x",
       (unsigned char)item->ifr_hwaddr.sa_data[0],
       (unsigned char)item->ifr_hwaddr.sa_data[1],
       (unsigned char)item->ifr_hwaddr.sa_data[2],
       (unsigned char)item->ifr_hwaddr.sa_data[3],
       (unsigned char)item->ifr_hwaddr.sa_data[4],
       (unsigned char)item->ifr_hwaddr.sa_data[5]);
    
#elif SIOCGENADDR
    /* Solaris and possibly all SysVR4 */
    /* Get the MAC address */
    if(ioctl(sck, SIOCGENADDR, item) < 0) {
      fatal_perror("ioctl(SIOCGENADDR)");
    }
    
    /* display result */
    printf(" %02x:%02x:%02x:%02x:%02x:%02x",
       (unsigned char)item->ifr_enaddr[0],
       (unsigned char)item->ifr_enaddr[1],
       (unsigned char)item->ifr_enaddr[2],
       (unsigned char)item->ifr_enaddr[3],
       (unsigned char)item->ifr_enaddr[4],
       (unsigned char)item->ifr_enaddr[5]);
    
#elif __MACH__ || __NetBSD__ || __OpenBSD__ || __FreeBSD__
    /* MacOS X and all modern BSD implementations (I hope) */
    int                mib[6] = {0};
    int                len = 0;
    char               *macbuf; 
    struct if_msghdr   *ifm;
    struct sockaddr_dl *sdl;
    unsigned char      *ptr;
      
    mib[0] = CTL_NET;
    mib[1] = AF_ROUTE;
    mib[2] = 0;
    mib[3] = AF_LINK;
    mib[4] = NET_RT_IFLIST;
    mib[5] = if_nametoindex(item->ifr_name);
    if(mib[5] == 0)
      continue;

    if(sysctl(mib, 6, NULL, (size_t*)&len, NULL, 0) != 0) {
      fatal_perror("sysctl");
    }

    macbuf = (char *) malloc(len);
    if(macbuf == NULL) {
      fprintf(stderr, "\nUnable to allocate necessary memory: %d\n", len);
      exit(1);
    }

    if(sysctl(mib, 6, macbuf, (size_t*)&len, NULL, 0) != 0) {
      fatal_perror("sysctl");
    }

    ifm = (struct if_msghdr *)macbuf;
    sdl = (struct sockaddr_dl *)(ifm + 1);
    ptr = (unsigned char *)LLADDR(sdl);

    printf(" %02x:%02x:%02x:%02x:%02x:%02x", 
       ptr[0], ptr[1], ptr[2], 
       ptr[3], ptr[4], ptr[5]);

    free(macbuf);
      
#else
#error OS Distribution Not Recognized
#endif

    printf(" %s\n", hostname);

    free(flagsStruct);

  }

  return 0;
}
Ejemplo n.º 5
0
void server(int lpnumber)
{
	struct rlimit resourcelimit;
#ifdef	USE_GETPROTOBYNAME
	struct protoent *proto;
#endif
	int netfd = -1, fd, lp, one = 1;
	int open_sleep = 10;
	socklen_t clientlen;
	struct sockaddr_storage client;
	struct addrinfo hints, *res, *ressave;
	char pidfilename[sizeof(PIDFILE)];
	char service[10];	// 9100 (65535 max)
	FILE *f;
	const int bufsiz = 65536;

#ifndef	TESTING
	if (!log_to_stdout)
	{
		switch (fork()) {
		case -1:
			dolog(LOGOPTS, "fork: %m\n");
			exit(1);
		case 0:		/* child */
			break;
		default:		/* parent */
			exit(0);
		}
		/* Now in child process */
		resourcelimit.rlim_max = 0;
		if (getrlimit(RLIMIT_NOFILE, &resourcelimit) < 0) {
			dolog(LOGOPTS, "getrlimit: %m\n");
			exit(1);
		}
		for (fd = 0; fd < resourcelimit.rlim_max; ++fd)
			(void)close(fd);
		if (setsid() < 0) {
			dolog(LOGOPTS, "setsid: %m\n");
			exit(1);
		}
		(void)chdir("/");
		(void)umask(022);
		fd = open("/dev/null", O_RDWR);	/* stdin */
		(void)dup(fd);		/* stdout */
		(void)dup(fd);		/* stderr */
		(void)snprintf(pidfilename, sizeof(pidfilename), PIDFILE, lpnumber);
		if ((f = fopen(pidfilename, "w")) == NULL) {
			dolog(LOGOPTS, "%s: %m\n", pidfilename);
			exit(1);
		}
		(void)fprintf(f, "%d\n", getpid());
		(void)fclose(f);
	}
	if (get_lock(lpnumber) == 0)
		exit(1);
#endif
	memset(&hints, 0, sizeof(hints));
	hints.ai_family = PF_UNSPEC;
	hints.ai_flags = AI_PASSIVE;
	hints.ai_socktype = SOCK_STREAM;
	(void)snprintf(service, sizeof(service), "%hu", (BASEPORT + lpnumber - '0'));
	if (getaddrinfo(bindaddr, service, &hints, &res) != 0) {
		dolog(LOGOPTS, "getaddr: %m\n");
		exit(1);
	}
	ressave = res;
	while (res) {
#ifdef	USE_GETPROTOBYNAME
		if ((proto = getprotobyname("tcp6")) == NULL) {
			if ((proto = getprotobyname("tcp")) == NULL) {
				dolog(LOGOPTS, "Cannot find protocol for TCP!\n");
				exit(1);
			}
		}
		if ((netfd = socket(res->ai_family, res->ai_socktype, proto->p_proto)) < 0)
#else
		if ((netfd = socket(res->ai_family, res->ai_socktype, IPPROTO_IP)) < 0)
#endif
		{
			dolog(LOGOPTS, "socket: %m\n");
			close(netfd);
			res = res->ai_next;
			continue;
		}
		if (setsockopt(netfd, SOL_SOCKET, SO_RCVBUF, &bufsiz, sizeof(bufsiz)) < 0) {
			dolog(LOGOPTS, "setsocketopt: SO_RCVBUF: %m\n");
			/* not fatal if it fails */
		}
		if (setsockopt(netfd, SOL_SOCKET, SO_SNDBUF, &bufsiz, sizeof(bufsiz)) < 0) {
			dolog(LOGOPTS, "setsocketopt: SO_SNDBUF: %m\n");
			/* not fatal if it fails */
		}
		if (setsockopt(netfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0) {
			dolog(LOGOPTS, "setsocketopt: SO_REUSEADDR: %m\n");
			close(netfd);
			res = res->ai_next;
			continue;
		}
		if (bind(netfd, res->ai_addr, res->ai_addrlen) < 0) {
			dolog(LOGOPTS, "bind: %m\n");
			close(netfd);
			res = res->ai_next;
			continue;
		}
		if (listen(netfd, 5) < 0) {
			dolog(LOGOPTS, "listen: %m\n");
			close(netfd);
			res = res->ai_next;
			continue;
		}
		break;
	}
	freeaddrinfo(ressave);
	clientlen = sizeof(client);
	memset(&client, 0, sizeof(client));
	while ((fd = accept(netfd, (struct sockaddr *)&client, &clientlen)) >= 0) {
		char host[INET6_ADDRSTRLEN];
#ifdef	USE_LIBWRAP
		if (hosts_ctl("p910nd", STRING_UNKNOWN, get_ip_str((struct sockaddr *)&client, host, sizeof(host)), STRING_UNKNOWN) == 0) {
			dolog(LOGOPTS,
			       "Connection from %s port %hu rejected\n", get_ip_str((struct sockaddr *)&client, host, sizeof(host)), get_port((struct sockaddr *)&client));
			close(fd);
			continue;
		}
#endif
		dolog(LOG_NOTICE, "Connection from %s port %hu accepted\n", get_ip_str((struct sockaddr *)&client, host, sizeof(host)), get_port((struct sockaddr *)&client));
		/*write(fd, "Printing", 8); */

		/* Make sure lp device is open... */
		while ((lp = open_printer(lpnumber)) == -1) {
			sleep(open_sleep);
			if (open_sleep < 320) /* ~5 min interval to avoid spam in syslog */
				open_sleep *= 2;
		}
		open_sleep = 10;

		if (copy_stream(fd, lp) < 0)
			dolog(LOGOPTS, "copy_stream: %m\n");
		(void)close(fd);
		(void)close(lp);
	}
	dolog(LOGOPTS, "accept: %m\n");
	free_lock();
	exit(1);
}
Ejemplo n.º 6
0
int main(int argc, char *argv[])
{
	int get_tmp = 1, get_cmd;

	if(argc < 3) {
		print_help(argv[0]);
		exit(2);
	}

	int option_index = 0;
	static struct option long_options[] = {
		{ "mac", required_argument, 0, 'm' },
		{ "interface", required_argument, 0, 'i' },
		{ "vlan", required_argument, 0, 'v' },
		{ "dhcp_xid", required_argument, 0, 'x' },
		{ "tos", required_argument, 0, 't' },
		{ "option51-lease_time", required_argument, 0, 'L' },
		{ "option50-ip", required_argument, 0, 'I' },
		{ "option60-vci", required_argument, 0, 'o' },
		{ "option12-hostname", required_argument, 0, 'h' },
		{ "timeout", required_argument, 0, 'T' },
		{ "bind-ip", no_argument, 0, 'b' },
		{ "bind-timeout", required_argument, 0, 'k' },
		{ "bcast_flag", no_argument, 0, 'f'},
		{ "verbose", no_argument, 0, 'V'},
		{ "fqdn-server-not-update", no_argument, 0, 'n'},
		{ "fqdn-server-update-a", no_argument, 0, 's'},
		{ "fqdn-domain-name", required_argument, 0, 'd'},
		{ "padding", no_argument, 0, 'p'},
		{ "port", required_argument, 0, 'P'},
		{ "giaddr", required_argument, 0, 'g'},
		{ "unicast", optional_argument, 0, 'u'},
		{ "nagios", no_argument, 0, 'a'},
		{ "server", required_argument, 0, 'S'},
		{ "release", no_argument, 0, 'r'},
		{ 0, 0, 0, 0 }
	};

	/*getopt routine to get command line arguments*/
	while(get_tmp < argc) {
		get_cmd  = getopt_long(argc, argv, "m:i:v:t:bfVrpansu::T:P:g:S:I:o:k:L:h:d:",\
				long_options, &option_index);
		if(get_cmd == -1 ) {
			break;
		}
		switch(get_cmd) {
			case 'm':
				{
					u_char aux_dhmac[ETHER_ADDR_LEN + 1];

					if(strlen(optarg) > 18) {
						fprintf(stdout, "Invalid mac address\n");
						exit(2);
					}
					strcpy(dhmac_fname, optarg);
					sscanf((char *)optarg, "%2X:%2X:%2X:%2X:%2X:%2X",
							(u_int32_t *) &aux_dhmac[0], (u_int32_t *) &aux_dhmac[1],
							(u_int32_t *) &aux_dhmac[2], (u_int32_t *) &aux_dhmac[3],
							(u_int32_t *) &aux_dhmac[4], (u_int32_t *) &aux_dhmac[5]);
					memcpy(dhmac, aux_dhmac, sizeof(dhmac));
					dhmac_flag = 1;
				}
				break;

			case 'i':
				iface = if_nametoindex(optarg);
				if(iface == 0) {
					fprintf(stdout, "Interface doesnot exist\n");
					exit(2);
				}
				strncpy(iface_name, optarg, 29);
				break;

			case 'v':
				if(atoi(optarg) < 1 || atoi(optarg) > 4095)
				{
					fprintf(stdout, "VLAN ID is not valid. Range 1 to 4095\n");
					exit(2);
				}
				vlan = atoi(optarg);
				l2_hdr_size = 18;
				break;

			case 'r':
				dhcp_release_flag = 1;
				break;

			case 'b':
				ip_listen_flag = 1;
				break;

			case 'k':
				listen_timeout = atoi(optarg);
				tval_listen.tv_sec = listen_timeout;
				break;

			case 'x':
				{
					u_int32_t aux_dhcp_xid[2];
					aux_dhcp_xid[0] = 0;
					sscanf((char *)optarg, "%X", &aux_dhcp_xid[0]);
					dhcp_xid = aux_dhcp_xid[0];
				}
				break;

			case 't':
				if(atoi(optarg) >= 256 || atoi(optarg) < 0) {
					fprintf(stdout, "Invalid TOS value\n");
					exit(2);
				}
				l3_tos = atoi(optarg);
				break;

			case 'L':
				option51_lease_time = atoi(optarg);
				break;

			case 'I':
				option50_ip = inet_addr(optarg);
				break;

			case 'o':
				if(strlen(optarg) > 256) {
					fprintf(stdout, "VCI string size should be less than 256\n");
					exit(2);
				}
				vci_flag = 1;
				memcpy(vci_buff, optarg, sizeof(vci_buff));
				break;

			case 'h':
				if(strlen(optarg) > 256) {
					fprintf(stdout, "Hostname string size should be less than 256\n");
					exit(2);
				}
				hostname_flag = 1;
				memcpy(hostname_buff, optarg, sizeof(hostname_buff));
				break;

			case 'd':
				if(strlen(optarg) > 256) {
					fprintf(stdout, "FQDN domain name string size should be less than 256\n");
					exit(2);
				}
				fqdn_flag = 1;
				memcpy(fqdn_buff, optarg, sizeof(fqdn_buff));
				break;

			case 'n':
				fqdn_n = 1;
				break;

			case 's':
				fqdn_s = 1;
				break;

			case 'T':
				if(atoi(optarg) < 5 || atoi(optarg) > 3600) {
					fprintf(stdout, "Invalid timout value. Range 5 to 3600\n");
					exit(2);
				}
				timeout = atoi(optarg);
				break;

			case 'P':
				if(atoi(optarg) <=0 || atoi(optarg) > 65535) {
					fprintf(stdout, "Invalid portt value. Range 1 to 65535\n");
					exit(2);
				}
				port = atoi(optarg);
				break;

			case 'g':
				giaddr = optarg;
				break;

			case 'S':
				server_addr = optarg;
				break;

			case 'p':
				padding_flag = 1;
				break;

			case 'f':
				bcast_flag = htons(0x8000);
				break;

			case 'V':
				verbose = 1;
				break;

			case 'u':
				if (optarg) {
					struct in_addr out;

					if (!inet_aton(optarg, &out)) {
						fprintf(stdout, "Invalid unicast IP address.");
						exit(2);
					}
					unicast_ip_address = out.s_addr;
				}
				unicast_flag = 1;
				break;

			case 'a':
				nagios_flag = 1;
				break;

			default:
				exit(2);
		}
		get_tmp++;
	}	

	if(!dhmac_flag) {
		print_help(argv[0]);
		exit(2);
	}
	/* Opens the PF_PACKET socket */
	if(open_socket() < 0) {
		if (nagios_flag)
			fprintf(stdout, "CRITICAL: Socket error.");
		else
			fprintf(stdout, "Socket error\n");
		exit(2);
	}

	/* Sets the promiscuous mode */
	set_promisc();

	if (unicast_flag && !unicast_ip_address) {
		unicast_ip_address = get_interface_address();
	}

	/* Sets a random DHCP xid */
	set_rand_dhcp_xid(); 

	/*
	 * If DHCP release flag is set, send DHCP release packet
	 * and exit. get_dhinfo parses the DHCP info from log file
	 * and unlinks it from the system
	 */
	if(dhcp_release_flag) {
		if(get_dhinfo() == ERR_FILE_OPEN) {
			if (nagios_flag) {
				fprintf(stdout, "CRITICAL: Error on opening DHCP info file.");
			} else {
				fprintf(stdout, "Error on opening DHCP info file\n");
				fprintf(stdout, "Release the DHCP IP after acquiring\n");
			}
			exit(2);
		}
		build_option53(DHCP_MSGRELEASE); /* Option53 DHCP release */
		if(hostname_flag) {
			build_option12_hostname();
		}
		if(fqdn_flag) {
			build_option81_fqdn();
		}
		build_option54();		 /* Server id */
		build_optioneof();		 /* End of option */
		build_dhpacket(DHCP_MSGRELEASE); /* Build DHCP release packet */
		send_packet(DHCP_MSGRELEASE);	 /* Send DHCP release packet */
		clear_promisc();		 /* Clear the promiscuous mode */
		close_socket();
		return 0; 
	}
	if(timeout) {
		time_last = time(NULL);
	}
	build_option53(DHCP_MSGDISCOVER);	/* Option53 for DHCP discover */
	if(hostname_flag) {
		build_option12_hostname();
	}
	if(fqdn_flag) {
		build_option81_fqdn();
	}
	if(option50_ip) {
		build_option50();		/* Option50 - req. IP  */
	}
	if(option51_lease_time) {
		build_option51();               /* Option51 - DHCP lease time requested */
	}

	if(vci_flag == 1) {
		build_option60_vci(); 		/* Option60 - VCI  */
	}
	build_optioneof();			/* End of option */
	build_dhpacket(DHCP_MSGDISCOVER);	/* Build DHCP discover packet */

	int dhcp_offer_state = 0;
	while(dhcp_offer_state != DHCP_OFFR_RCVD) {

		/* Sends DHCP discover packet */
		send_packet(DHCP_MSGDISCOVER);
		/*
		 * recv_packet functions returns when the specified 
		 * packet is received
		 */
		dhcp_offer_state = recv_packet(DHCP_MSGOFFER); 

		if(timeout) {
			time_now = time(NULL);
			if((time_now - time_last) > timeout) {
				if (nagios_flag)
					fprintf(stdout, "CRITICAL: Timeout reached: DISCOVER.");
				close_socket();
				exit(2);
			}
		}
		if(dhcp_offer_state == DHCP_OFFR_RCVD) {
			if (!nagios_flag)
				fprintf(stdout, "DHCP offer received\t - ");
			set_serv_id_opt50();
			if (!nagios_flag)
  				fprintf(stdout, "Offered IP : %s\n", get_ip_str(dhcph_g->dhcp_yip));
			if(!nagios_flag && verbose) { 
				print_dhinfo(DHCP_MSGOFFER);
			}
		}
	}
	/* Reset the dhopt buffer to build DHCP request options  */
	reset_dhopt_size();
	build_option53(DHCP_MSGREQUEST); 
	build_option50();
	build_option54();
	if(hostname_flag) {
		build_option12_hostname();
	}
	if(fqdn_flag) {
		build_option81_fqdn();
	}
	if(vci_flag == 1) {
		build_option60_vci();  
	}
	if(option51_lease_time) {
		build_option51();                       /* Option51 - DHCP lease time requested */
	}
	build_option55();
	build_optioneof();
	build_dhpacket(DHCP_MSGREQUEST); 		/* Builds specified packet */
	int dhcp_ack_state = 1;
	while(dhcp_ack_state != DHCP_ACK_RCVD) { 

		send_packet(DHCP_MSGREQUEST);
		dhcp_ack_state = recv_packet(DHCP_MSGACK); 

		if(timeout) {
			time_now = time(NULL);
			if((time_now - time_last) > timeout) {
				if (nagios_flag)
					fprintf(stdout, "CRITICAL: Timeout reached: REQUEST.");
				else
					fprintf(stdout, "Timeout reached. Exiting\n");
				close_socket();
				exit(1);
			}
		}

		if(dhcp_ack_state == DHCP_ACK_RCVD) {
			if (nagios_flag) {
				fprintf(stdout, "OK: Acquired IP: %s", get_ip_str(dhcph_g->dhcp_yip));
			} else {
				fprintf(stdout, "DHCP ack received\t - ");
				fprintf(stdout, "Acquired IP: %s\n", get_ip_str(dhcph_g->dhcp_yip));
			}

			/* Logs DHCP IP details to log file. This file is used for DHCP release */
			log_dhinfo(); 
			if(!nagios_flag && verbose) {
				print_dhinfo(DHCP_MSGACK);
			}
		} else if (dhcp_ack_state == DHCP_NAK_RCVD) {
			if (!nagios_flag) {
				fprintf(stdout, "DHCP nack received\t - ");
				fprintf(stdout, "Client MAC : %02x:%02x:%02x:%02x:%02x:%02x\n", \
					dhmac[0], dhmac[1], dhmac[2], dhmac[3], dhmac[4], dhmac[5]); 
			}
		}
	}
	/* If IP listen flag is enabled, Listen on obtained for ARP, ICMP protocols  */
	if(!nagios_flag && ip_listen_flag) {
		fprintf(stdout, "\nListening on %s for ARP and ICMP protocols\n", iface_name);
		fprintf(stdout, "IP address: %s, Listen timeout: %d seconds\n", get_ip_str(htonl(ip_address)), listen_timeout);
		int arp_icmp_rcv_state = 0;
		while(arp_icmp_rcv_state != LISTEN_TIMOUET) { 
			arp_icmp_rcv_state = recv_packet(ARP_ICMP_RCV);
			/* Send ARP reply if ARP request received */
			if(arp_icmp_rcv_state == ARP_RCVD) {
				/*if(verbose) {
				  fprintf(stdout, "ARP request received\n");
				  fprintf(stdout, "Sending ARP reply\n");
				  }*/
				build_packet(ARP_SEND);
				send_packet(ARP_SEND);
			} else if(arp_icmp_rcv_state == ICMP_RCVD) {
				/* Send ICMP reply if ICMP echo request received */
				/*if(verbose) {
				  fprintf(stdout, "ICMP request received\n");
				  fprintf(stdout, "Sending ICMP reply\n");
				  }*/
				build_packet(ICMP_SEND);
				send_packet(ICMP_SEND);  
			} 
		}
		fprintf(stdout, "Listen timout reached\n");
	}
	/* Clear the promiscuous mode */
	clear_promisc();
	/* Close the socket */
	close_socket();
	return 0;
}
Ejemplo n.º 7
0
/* wait for incoming connection requests */
void wait_for_connections(void){
	struct sockaddr_in6 myname6;
	struct sockaddr_in6 src_sin;
	socklen_t socklen = sizeof(src_sin);
	struct sockaddr *remoteaddr = (struct sockaddr *)&src_sin;
	int rc;
	int sock, new_sd;
	pid_t pid;
	int flag=1;
	int max_fd = 0;
	int i = 0, j = 0;
	fd_set fdread;
	struct timeval timeout;
	int retval;
#ifdef HAVE_LIBWRAP
	struct request_info req;
#endif

	int rval;
	struct addrinfo addrinfo;
	struct addrinfo *res, *r;

	memset(&addrinfo, 0, sizeof(addrinfo));
	addrinfo.ai_family=AF_UNSPEC;
	addrinfo.ai_socktype=SOCK_STREAM;
	addrinfo.ai_protocol=IPPROTO_TCP;

	if(!server_address || !strlen(server_address)) {
		server_address = NULL;
		addrinfo.ai_flags=AI_PASSIVE;
		}
	if (rval = getaddrinfo(server_address, server_port, &addrinfo, &res) != 0) {
		syslog(LOG_ERR,"Invalid server_address (%d: %s)",errno,strerror(errno));
		exit(STATE_CRITICAL);
		}
	else {
		for (r=res; r; r = r->ai_next){
			if (r->ai_family != AF_INET && r->ai_family != AF_INET6)
				continue;
			if (num_listen_socks >= MAX_LISTEN_SOCKS){
				syslog(LOG_ERR,"Too many listen sockets. Enlarge MAX_LISTEN_SOCKS\n");
				exit(STATE_UNKNOWN);
				}
			sock = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
			if (sock < 0)
				/* kernel may not support ipv6 */
				continue;
			/* socket should be non-blocking */
			fcntl(sock,F_SETFL,O_NONBLOCK);
			/* set the reuse address flag so we don't get errors when restarting */
			flag=1;
			if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char *)&flag,sizeof(flag))<0){
				syslog(LOG_ERR,"Could not set reuse address option on socket!\n");
				exit(STATE_UNKNOWN);
				}
#ifdef IPV6_V6ONLY
			/* Only communicate in IPv6 over AF_INET6 sockets. */
			flag=1;
			if (r->ai_family == AF_INET6)
				if(setsockopt(sock,IPPROTO_IPV6,IPV6_V6ONLY,(char *)&flag,sizeof(flag))<0) {
					syslog(LOG_ERR,"Could not set IPV6_V6ONLY option on socket!\n");
					exit(STATE_UNKNOWN);
					}
#endif
			if(bind(sock, r->ai_addr, r->ai_addrlen) < 0) {
				syslog(LOG_ERR,"Network server bind failure (%d: %s)\n",errno,strerror(errno));
				(void) close(sock);
				exit(STATE_CRITICAL);
				}
			listen_socks[num_listen_socks] = sock;
			num_listen_socks++;
			if (listen(sock, 5) < 0){
				syslog(LOG_ERR,"Network server listen failure (%d: %s)\n",errno,strerror(errno));
	        		exit(STATE_CRITICAL);
				}
			if(sock > max_fd)
				max_fd = sock;
			}
		freeaddrinfo(res);
		if(num_listen_socks == 0) {
			exit(STATE_CRITICAL);
			}
		}


	/* log warning about command arguments */
#ifdef ENABLE_COMMAND_ARGUMENTS
	if(allow_arguments==TRUE)
		syslog(LOG_NOTICE,"Warning: Daemon is configured to accept command arguments from clients!");
#endif

	syslog(LOG_INFO,"Listening for connections on port %s\n",server_port);

	if(allowed_hosts)
		syslog(LOG_INFO,"Allowing connections from: %s\n",allowed_hosts);

	/* listen for connection requests - fork() if we get one */
	while(1){

		/* wait for a connection request */

		/* wait until there's something to do */
		FD_ZERO(&fdread);
		for(i=0; i < num_listen_socks; i++)
			FD_SET(listen_socks[i],&fdread);

		timeout.tv_sec=0;
		timeout.tv_usec=500000;
		retval=select(max_fd+1,&fdread,NULL,NULL,&timeout);
		/* bail out if necessary */
		if(sigrestart==TRUE || sigshutdown==TRUE)
			break;

		/* error */
		if(retval<0)
			continue;

		/* accept a new connection request */
		for (i = 0; i < num_listen_socks; i++){
			if (!FD_ISSET(listen_socks[i], &fdread))
				continue;
			new_sd=accept(listen_socks[i], remoteaddr, &socklen);

			/* some kind of error occurred... */
			if(new_sd<0){
				/* bail out if necessary */
				if(sigrestart==TRUE || sigshutdown==TRUE)
					break;

				/* retry */
				if(errno==EWOULDBLOCK || errno==EINTR)
					continue;

				/* socket is nonblocking and we don't have a connection yet */
				if(errno==EAGAIN)
					continue;

				/* fix for HP-UX 11.0 - just retry */
				if(errno==ENOBUFS)
					continue;

			        }		

			/* bail out if necessary */
			if(sigrestart==TRUE || sigshutdown==TRUE)
				break;

			/* child process should handle the connection */
	    		pid=fork();
	    		if(pid==0){

				/* fork again so we don't create zombies */
				pid=fork();
				if(pid==0){
					/* hey, there was an error... */
					if(new_sd<0){

						/* log error to syslog facility */
						syslog(LOG_ERR,"Network server accept failure (%d: %s)",errno,strerror(errno));

						/* close sockets prioer to exiting */
						for(j=0; j < num_listen_socks; j++)
							close(listen_socks[j]);
			
						return;
					        }

					/* handle siOAgnals */
					signal(SIGQUIT,child_sighandler);
					signal(SIGTERM,child_sighandler);
					signal(SIGHUP,child_sighandler);

					/* grandchild does not need to listen for connections, so close the sockets */
					for(j=0; j < num_listen_socks; j++)
						close(listen_socks[j]);

					/* log info to syslog facility */
					if(debug==TRUE)
						syslog(LOG_DEBUG,"Connection from %s port %d",get_ip_str(remoteaddr, buf, BUFLEN),get_port(remoteaddr));

                                	/* is this is a blessed machine? */
					if(allowed_hosts){
						if(!is_an_allowed_host(remoteaddr)){
							/* log error to syslog facility */
							syslog(LOG_ERR,"Host %s is not allowed to talk to us!",get_ip_str(remoteaddr, buf, BUFLEN));

							/* log info to syslog facility */
							if(debug==TRUE)
								syslog(LOG_DEBUG,"Connection from %s closed.",get_ip_str(remoteaddr, buf, BUFLEN));

							/* close socket prior to exiting */
							close(new_sd);

							exit(STATE_OK);
							}
						else{

							/* log info to syslog facility */
							if(debug==TRUE)
							syslog(LOG_DEBUG,"Host address is in allowed_hosts");
							}
						}

#ifdef HAVE_LIBWRAP

					/* Check whether or not connections are allowed from this host */
					request_init(&req,RQ_DAEMON,"nrpe",RQ_FILE,new_sd,0);
					fromhost(&req);

					if(!hosts_access(&req)){

						syslog(LOG_DEBUG,"Connection refused by TCP wrapper");

						/* refuse the connection */
						refuse(&req);
						close(new_sd);

						/* should not be reached */
						syslog(LOG_ERR,"libwrap refuse() returns!");
						exit(STATE_CRITICAL);
						}
#endif

					/* handle the client connection */
					handle_connection(new_sd);

					/* log info to syslog facility */
					if(debug==TRUE)
						syslog(LOG_DEBUG,"Connection from %s closed.",get_ip_str(remoteaddr, buf, BUFLEN));

					/* close socket prior to exiting */
					close(new_sd);

					exit(STATE_OK);
    			        	}

				/* first child returns immediately, grandchild is inherited by INIT process -> no zombies... */
				else
					exit(STATE_OK);
		        	}
		
			/* parent ... */
			else{
				/* parent doesn't need the new connection */
				close(new_sd);

				/* parent waits for first child to exit */
				waitpid(pid,NULL,0);
		        	}
  			}
		}
		/* close the sockets we're listening on */
		for(j=0; j < num_listen_socks; j++)
			close(listen_socks[j]);

		return;
	}
Ejemplo n.º 8
0
void printf_addr(const struct sockaddr *sa) {
	char str[INET6_ADDRSTRLEN];
	get_ip_str(sa, str, INET6_ADDRSTRLEN);
	printf("%s", str);
}
Ejemplo n.º 9
0
int
main(int argc, char** argv){
    int activeSockets = 0;
    int c;
    char* host = "127.0.0.1";
    int sockfd[MAX_SUBSTREAMS];
    int substreams = 1;

    char buff[BUFSIZE];

    while((c = getopt(argc, argv, "h:s:")) != -1){
        switch(c){
        case 'h':
            host = optarg;
            break;
        case 's':
            substreams = atoi(optarg);
            break;
        default:
            printf("Usage: ./demoClient -h host [-m message]\n");
            exit(1);
        }
    }

    struct sockaddr srvAddr;
    socklen_t srvAddrLen = sizeof srvAddr;
    char            ip[INET6_ADDRSTRLEN] = {0};
    struct addrinfo hints, *servInfo;
    struct addrinfo *result;
    int numbytes;
    int rv;

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_DGRAM;

    if((rv = getaddrinfo(host, SERVERPORT, &hints, &servInfo)) != 0) {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
        return 1;
    }

    char            buf[8192] = {0};
    struct ifconf   ifc = {0};
    struct ifreq   *ifr = NULL;
    int             nInterfaces = 0;
    int             i = 0;
    struct ifreq    *item;
    struct sockaddr *addr;
    char            hostname[NI_MAXHOST];

    // loop through all the results and bind to the first possible
loop:
    for(result = servInfo; result != NULL; result = result->ai_next) {
        int i;
        for(i = 0; i < MAX_SUBSTREAMS; i++)
        {
            printf("Initializing socket %d\n", i);
            if((sockfd[i] = socket(result->ai_family,
                                   result->ai_socktype,
                                   result->ai_protocol)) == -1)
            {
                perror("failed to initialize sokcket %d\n");
                goto loop;
            }
        }

        break;
    }

    // If we got here, it means that we couldn't initialize the socket.
    if(result  == NULL){
        perror("failed to create a socket");
        exit(1);
    }

    printf("socket initi success\n");

    /* Query available interfaces. */
    ifc.ifc_len = sizeof(buf);
    ifc.ifc_buf = buf;
    if(ioctl(sockfd[0], SIOCGIFCONF, &ifc) < 0)
    {
        perror("ioctl(SIOCGIFCONF)");
        exit(1);
    }

    /* Iterate through the list of interfaces. */
    ifr = ifc.ifc_req;
    nInterfaces = ifc.ifc_len / sizeof(struct ifreq);
    printf("We have a total of %d interfaces\n", nInterfaces);
    for(i = 0; i < nInterfaces; i++) {
        memset(hostname, 0, NI_MAXHOST);

        item = &ifr[i];
        addr = &(item->ifr_addr);

        /* Get the address
         * This may seem silly but it seems to be needed on some systems
         */
        if(ioctl(sockfd[0], SIOCGIFADDR, item) < 0) {
            perror("ioctl(OSIOCGIFADDR)");
            exit(1);
        }

        if(strcmp(item->ifr_name,"lo") == 0) continue;

        printf("Binding socket %d to %s %s\n",
               i, item->ifr_name,
               get_ip_str(addr, ip, INET6_ADDRSTRLEN));


        bind(sockfd[activeSockets], addr, srvAddrLen);

        activeSockets++;
    }


    int j = 0;
    while(1)
    {
        char* line = readline("Enter message:");

        printf("Got: %s\n", line);

        if((numbytes = sendto(sockfd[j % activeSockets], line, strlen(line), 0,
                              result->ai_addr, result->ai_addrlen)) == -1)
        {
            perror("DemoClient sendto failed");
        }

        if((numbytes = recvfrom(sockfd[j % activeSockets], buff, BUFSIZE, 0,
                                &srvAddr, &srvAddrLen)) == -1)
        {
            perror("DemoClient recvfrom failed");
        }

        j++;

        if(strlen(buff) == 0)
        {
            printf("Exiting Client...\n");
            for(j = 0; j < substreams; j++)
            {
                close(sockfd[j]);
            }
            break;
        }

        int i = 0;
        for(i=0; i < numbytes; i++)
        {
            printf("%c", buff[i]);
        }
        printf("\n");
    }

    return 0;
}
Ejemplo n.º 10
0
int 
dia_dns_lookup(const char *server, void *dst) {
	struct addrinfo *res, *best;
	struct addrinfo hints;
	static char addrstr[256];
	int error;
	coap_list_t *node;
	dns_cache_t *entry;

	if	(server && *server)
		strcpy (addrstr, server);
	else
		strcpy (addrstr, "localhost");

	//	Already in cache ?
	for	(node = gCache; node; node = node->next) {
		entry	= (dns_cache_t *)node->data;
		if	(!strcmp(addrstr, entry->host)) {
			rtl_trace (5, "dns_lookup : %s found in cache\n", addrstr);
			memcpy (dst, &entry->dst, entry->len);
			return	entry->len;
		}
	}

//	rtl_trace (5, "dns_lookup : %s not found. search in DNS\n", addrstr);

	//	DNS lookup

	memset ((char *)&hints, 0, sizeof(hints));
	hints.ai_socktype = SOCK_DGRAM;
	hints.ai_family = AF_UNSPEC;
#ifdef ANDROID
	error = getaddrinfo(addrstr, NULL, &hints, &res);
#else
	error = getaddrinfo(addrstr, "", &hints, &res);
#endif

	//error = getaddrinfo(addrstr, NULL, NULL, &res);

	if (error) {
		rtl_trace (4, "getaddrinfo: %s\n", gai_strerror(error));
		return -1;
	}

	best	= searchBest (res);
	if	(!best)	return 0;

	int len = best->ai_addrlen;
	memcpy(dst, best->ai_addr, len);

	//	Create DNS cache entry
	entry	= (dns_cache_t *)malloc(sizeof(dns_cache_t));
	strcpy (entry->host, addrstr);
	memcpy(&entry->dst, best->ai_addr, len);
	entry->len	= len;

	char tmp[100];
	rtl_trace (5, "dns_lookup : %s found in DNS %s %s\n", addrstr, get_ip_fam(dst), get_ip_str(dst, tmp, sizeof(tmp)));

	//	Add to the list
	node = coap_new_listnode((void *)entry, NULL);
	coap_insert( &gCache, node, _order_null);

	freeaddrinfo(res);
	return len;
}
Ejemplo n.º 11
0
/* open listening socket and initialize */
void cann_listen(char *port)
{
        struct addrinfo hints;
        struct addrinfo *result, *rp;
        int sfd, s;
        char buf[200];
        int ret, one = 1;

        signal(SIGPIPE, SIG_IGN);

        memset(&hints, 0, sizeof(struct addrinfo));
        hints.ai_family = AF_UNSPEC;  // Allow IPv4 or IPv6 - ipv4 is mapped into an v6 addr -> ai_v4mapped
        hints.ai_socktype = SOCK_STREAM;                // Datagram socket
        hints.ai_flags = AI_PASSIVE | AI_V4MAPPED | AI_NUMERICSERV | AI_ALL;     // For wildcard IP address

        s = getaddrinfo(NULL, port, &hints, &result);
        if (s != 0) {
                fprintf(stderr,
                        "No listening addresses available(getaddrinfo: %s)\n",
                        gai_strerror(s));
                exit(EXIT_FAILURE);
        }

        //dump address info
        for (rp = result; rp != NULL; rp = rp->ai_next)
                debug(5, "Found Address %s\t\t(family: %s, socktype %i: protocol %i)",
                      get_ip_str((struct sockaddr *)rp->ai_addr,
                                 buf, sizeof(buf)),
                      (rp->ai_family == AF_INET) ? "IPv4" :
                      ((rp->ai_family == AF_INET6) ? "IPv6" :
                       ((snprintf(buf, sizeof(buf), "%i", rp->ai_family) != 0)
                        ? buf : "")),
                      rp->ai_socktype,
                      rp->ai_protocol);

        /* getaddrinfo() returns a list of address structures.
           Try each address until we successfully bind(2).
           If socket(2) (or bind(2)) fails, we (close the socket
           and) try the next address. */

        for (rp = result; rp != NULL; rp = rp->ai_next) {
                sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
                if (sfd == -1)
                        continue;

                debug(5, "Trying to bind to %s (%s)",
                      get_ip_str((struct sockaddr *)rp->ai_addr,
                                 buf, sizeof(buf)),
                      (rp->ai_family == AF_INET) ? "IPv4" :
                      ((rp->ai_family == AF_INET6) ? "IPv6" :
                       ((snprintf(buf, sizeof(buf), "%i", rp->ai_family) != 0)
                        ? buf : "")),
                      rp->ai_socktype,
                      rp->ai_protocol);

                //set reuseaddr to avoid address in use (b/c if close_wait) when restarting
                ret = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));

                if (ret != 0) debug_perror(0, "Could not set socket options: ");

                if (bind(sfd, rp->ai_addr, rp->ai_addrlen) == 0)
                        break;                  /* Success */

                debug_perror(0, "Could not bind to %s.",
                             get_ip_str((struct sockaddr *)rp->ai_addr,
                                        buf,
                                        sizeof(buf)));
                close(sfd);
        }

        if (rp == NULL) {               /* No address succeeded */
                debug_perror(0, "All addresses in use");
                exit(EXIT_FAILURE);
        } else debug(5, "Bind succeeded!");

        freeaddrinfo(result);           /* No longer needed */
        listen_socket = sfd;

        int flags = 0;
        flags = fcntl(listen_socket, F_GETFL, 0);
        fcntl(listen_socket, F_SETFL, flags | O_NDELAY);

        /* specify queue */
        ret = listen(listen_socket, SOMAXCONN);
        debug_assert(ret >= 0, "Could listen() listening socket");
}
Ejemplo n.º 12
0
/* open connection to cand */
cann_conn_t *cann_connect(char *server, char *port)
{
        struct addrinfo hints;
        struct addrinfo *result, *rp;
        int s;
        cann_conn_t *client;
        char buf[INET6_ADDRSTRLEN];

        // initialize client struct
        client = malloc(sizeof(cann_conn_t));
        if (client == NULL) {
                debug(0, "Could not allocate client buffer!\n");
                free(client);
                exit(EXIT_FAILURE);
        }
        client->state = CANN_LEN;
        client->missing_bytes = 0;
        client->error = 0;

#ifdef USE_WINSOCK
        WSADATA wsaData;
        int err;

        err = WSAStartup(0x0202, &wsaData);
        if (err != 0) {
                /* Tell the user that we could not find a usable */
                /* Winsock DLL.                                  */
                printf("WSAStartup failed with error: %d\n", err);
                exit(EXIT_FAILURE);
        }
#endif
        /* Obtain address(es) matching host/port */

        memset(&hints, 0, sizeof(struct addrinfo));
        hints.ai_family = AF_UNSPEC;    /* Allow IPv4 or IPv6 */
        hints.ai_socktype = SOCK_STREAM; /* Datagram socket */
        hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV; //
        hints.ai_protocol = 0;          /* Any protocol */

        s = getaddrinfo(server, port, &hints, &result);
        if (s != 0) {
                debug_perror(0, "getaddrinfo: %s\n", gai_strerror(s));
                free(client);
                exit(EXIT_FAILURE);
        }

        /* getaddrinfo() returns a list of address structures.
        Try each address until we successfully connect(2).
        If socket(2) (or connect(2)) fails, we (close the socket
        and) try the next address. */

        for (rp = result; rp != NULL; rp = rp->ai_next) {
                client->fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
                if (client->fd == -1)
                        continue;

                if (connect(client->fd, rp->ai_addr, rp->ai_addrlen) != -1)
                        break;                  /* Success */

                close(client->fd);
        }
        if (rp == NULL) {               /* No address succeeded */
                debug_perror(0, "Could not connect\n");
                free(client);
                exit(EXIT_FAILURE);
        }
        debug(4, "Connected to %s.", get_ip_str((struct sockaddr *)rp->ai_addr,
                                                buf,
                                                sizeof(buf)));


        freeaddrinfo(result);           /* No longer needed */
        listen_socket = client->fd;
#ifdef USE_WINSOCK
        u_long option = 1;
        ioctlsocket(client->fd, FIONBIO, &option);
#else
        // set some options on socket
        fcntl(client->fd, F_SETFL, O_NONBLOCK);
#endif

        int flag = 1;
        setsockopt(client->fd,
                   IPPROTO_TCP,     /* set option at TCP level */
                   TCP_NODELAY,     /* name of option */
                   (char *) &flag,  /* the cast is historical cruft */
                   sizeof(int));    /* length of option value */

        debug(9, "connected to server, fd=%d\r\n", client->fd);

        return client;
}
Ejemplo n.º 13
0
int main(int argc, char **argv)
{
	unsigned char pkt[MAXACARSLEN];
	char *basename = "acarsserv.sqb";
	char *bindaddr = "[::]";
	int c;
	int res;

	while ((c = getopt(argc, argv, "vb:N:asd")) != EOF) {

		switch (c) {
		case 'v':
			verbose = 1;
			break;
		case 'N':
			bindaddr = optarg;
			break;
		case 'b':
			basename = optarg;
			break;
		case 'a':
			allmess = 1;
			break;
		case 's':
			station = 1;
			break;
		case 'd':
			dupmess = 1;
			break;
		default:
			usage();
			exit(1);
		}
	}

	if (bindsock(bindaddr)) {
		fprintf(stderr, "failed to connect\n");
		exit(1);
	}

	if (initdb(basename)) {
		fprintf(stderr, "could not init sql base %s\n", basename);
		exit(1);
	}

	do {
		int len;
		acarsmsg_t *msg;
		struct tm tmp;
		char reg[8];
		char ipaddr[INET6_ADDRSTRLEN];
		struct sockaddr_in6 src_addr;
		socklen_t addrlen;
		char *mpt, *bpt;

		msg = calloc(sizeof(acarsmsg_t), 1);

		addrlen = sizeof(src_addr);
		bzero(&src_addr, addrlen);
		len =
		    recvfrom(sockfd, pkt, MAXACARSLEN, 0,
			     (struct sockaddr *)&src_addr, &addrlen);
		if (len <= 0) {
			fprintf(stderr, "read %d\n", len);
			continue;
		}

		if (len < 31) {
			continue;
		}
		pkt[len] = 0;

		mpt = pkt;
		bpt = mpt + 8;
		if (*bpt != ' ')
			continue;
		*bpt = '\0';
		strcpy(msg->idst, mpt);
		mpt = bpt + 1;
		bpt = mpt + 1;
		if (*bpt != ' ')
			continue;
		*bpt = '\0';
		msg->chn = atoi(mpt);
		mpt = bpt + 1;
		bpt = mpt + 2;
		if (*bpt != '/')
			continue;
		*bpt = '\0';
		tmp.tm_mday = atoi(mpt);
		mpt = bpt + 1;
		bpt = mpt + 2;
		if (*bpt != '/')
			continue;
		*bpt = '\0';
		tmp.tm_mon = atoi(mpt);
		mpt = bpt + 1;
		bpt = mpt + 4;
		if (*bpt != ' ')
			continue;
		*bpt = '\0';
		tmp.tm_year = atoi(mpt);
		mpt = bpt + 1;
		bpt = mpt + 2;
		if (*bpt != ':')
			continue;
		*bpt = '\0';
		tmp.tm_hour = atoi(mpt);
		mpt = bpt + 1;
		bpt = mpt + 2;
		if (*bpt != ':')
			continue;
		*bpt = '\0';
		tmp.tm_min = atoi(mpt);
		mpt = bpt + 1;
		bpt = mpt + 2;
		if (*bpt != ' ')
			continue;
		*bpt = '\0';
		tmp.tm_sec = atoi(mpt);
		mpt = bpt + 1;
		bpt = mpt + 1;
		if (*bpt != ' ')
			continue;
		msg->err = atoi(mpt);
		mpt = bpt + 1;
		bpt = mpt + 3;
		if (*bpt != ' ')
			continue;
		*bpt = '\0';
		msg->lvl = atoi(mpt);
		mpt = bpt + 1;
		bpt = mpt + 1;
		if (*bpt != ' ')
			continue;
		*bpt = '\0';
		msg->mode = *mpt;
		mpt = bpt + 1;
		bpt = mpt + 7;
		if (*bpt != ' ')
			continue;
		*bpt = '\0';
		strcpy(reg, mpt);
		mpt = bpt + 1;
		bpt = mpt + 1;
		if (*bpt != ' ')
			continue;
		*bpt = '\0';
		msg->ack = *mpt;
		mpt = bpt + 1;
		bpt = mpt + 2;
		if (*bpt != ' ')
			continue;
		*bpt = '\0';
		strcpy(msg->label, mpt);
		mpt = bpt + 1;
		bpt = mpt + 1;
		if (*bpt != ' ')
			continue;
		*bpt = '\0';
		msg->bid = *mpt;
		mpt = bpt + 1;
		bpt = mpt + 4;
		if (*bpt != ' ')
			continue;
		*bpt = '\0';
		strcpy(msg->no, mpt);
		mpt = bpt + 1;
		bpt = mpt + 6;
		if (*bpt != ' ')
			continue;
		*bpt = '\0';
		strcpy(msg->fid, mpt);
		mpt = bpt + 1;
		strncpy(msg->txt, mpt, 220);
		msg->txt[220] = '\0';


		fixreg(msg->reg, reg);

		tmp.tm_isdst = 0;
		tmp.tm_mon -= 1;
		tmp.tm_year -= 1900;
		msg->tm = timegm(&tmp);

		get_ip_str((struct sockaddr *)&src_addr, ipaddr,
			   INET6_ADDRSTRLEN);

		if (verbose)
			fprintf(stdout,
				"MSG %s %1d %1c %7s %1c %2s %1c %4s %6s %s\n",
				ipaddr, msg->chn, msg->mode, msg->reg, msg->ack,
				msg->label, msg->bid, msg->no, msg->fid,
				msg->txt);

		processpkt(msg, ipaddr);

		free(msg);
	} while (1);
}
Ejemplo n.º 14
0
int main(int argc, char *argv[])
{
	int get_tmp = 1, get_cmd;
	int dhinfo_ret;

	if(argc < 3) {
		print_help(argv[0]);
		exit(2);
	}

	init_rand();
	atexit(cleanup);
	signal(SIGSEGV, sigcleanup);
	signal(SIGABRT, sigcleanup);
	signal(SIGTERM, sigcleanup);
	signal(SIGINT, sigcleanup);
	signal(SIGHUP, sigcleanup);

	int option_index = 0;
	static struct option long_options[] = {
		{ "mac", required_argument, 0, 'm' },
		{ "random-mac", no_argument, 0, 'R' },
		{ "log-filename", required_argument, 0, 'F' },
		{ "interface", required_argument, 0, 'i' },
		{ "vlan", required_argument, 0, 'v' },
		{ "dhcp_xid", required_argument, 0, 'x' },
		{ "tos", required_argument, 0, 't' },
		{ "option51-lease_time", required_argument, 0, 'L' },
		{ "option50-ip", required_argument, 0, 'I' },
		{ "option60-vci", required_argument, 0, 'o' },
		{ "option12-hostname", required_argument, 0, 'h' },
		{ "timeout", required_argument, 0, 'T' },
		{ "bind-ip", no_argument, 0, 'b' },
		{ "bind-timeout", required_argument, 0, 'k' },
		{ "bcast_flag", no_argument, 0, 'f'},
		{ "verbose", no_argument, 0, 'V'},
		{ "fqdn-server-not-update", no_argument, 0, 'n'},
		{ "fqdn-server-update-a", no_argument, 0, 's'},
		{ "fqdn-domain-name", required_argument, 0, 'd'},
		{ "padding", no_argument, 0, 'p'},
		{ "port", required_argument, 0, 'P'},
		{ "giaddr", required_argument, 0, 'g'},
		{ "unicast", optional_argument, 0, 'u'},
		{ "nagios", no_argument, 0, 'a'},
		{ "server", required_argument, 0, 'S'},
		{ "release", no_argument, 0, 'r'},
		{ "quiet", no_argument, 0, 'q'},
		{ "request-only", no_argument, 0, 'Q'},
		{ 0, 0, 0, 0 }
	};

	/*getopt routine to get command line arguments*/
	while(get_tmp < argc) {
		get_cmd  = getopt_long(argc, argv, "m:Ri:v:t:bfVrpansu::T:P:g:S:I:o:k:L:h:d:F:qQ",\
				long_options, &option_index);
		if(get_cmd == -1 ) {
			break;
		}
		switch(get_cmd) {
			case 'q':
				quiet = 1;
				break;

			case 'm':
				{
					u_char aux_dhmac[ETHER_ADDR_LEN + 1];

					if(strlen(optarg) != 17
							|| sscanf(optarg, ETH_F_FMT, ETH_F_PARG(aux_dhmac)) != 6
					  )
					{
						fprintf(stderr, "Invalid mac address\n");
						exit(2);
					}
					memcpy(dhmac, aux_dhmac, sizeof(dhmac));
					dhmac_flag = 1;
				}
				break;

			case 'R':
				{
					int i;

					for (i = 0; i < ETHER_ADDR_LEN; i++)
						dhmac[i] = rand() & 0xff;

					/* clear multicast bit, set the L bit, clear MSB */
					dhmac[0] &= ~0x81;
					dhmac[0] |= 0x02;

					dhmac_flag = 1;
				}
				break;

			case 'F':
				if (strlen(optarg) > sizeof(dhmac_fname) - 1) {
					fprintf(stderr, "-F filename given is too long\n");
					exit(2);
				}
				strcpy(dhmac_fname, optarg);
				dhmac_fname_flag = 1;
				break;

			case 'i':
				iface_name = optarg;
				break;

			case 'v':
				if(atoi(optarg) < 1 || atoi(optarg) > 4095)
				{
					fprintf(stderr, "VLAN ID is not valid. Range 1 to 4095\n");
					exit(2);
				}
				vlan = atoi(optarg);
				l2_hdr_size = 18;
				break;

			case 'r':
				dhcp_release_flag = 1;
				break;

			case 'Q':
				dhcp_request_flag = 1;
				break;

			case 'b':
				ip_listen_flag = 1;
				break;

			case 'k':
				listen_timeout = atoi(optarg);
				tval_listen.tv_sec = listen_timeout;
				break;

			case 'x':
				{
					u_int32_t aux_dhcp_xid[2];
					aux_dhcp_xid[0] = 0;
					sscanf((char *)optarg, "%X", &aux_dhcp_xid[0]);
					dhcp_xid = aux_dhcp_xid[0];
				}
				break;

			case 't':
				if(atoi(optarg) >= 256 || atoi(optarg) < 0) {
					fprintf(stderr, "Invalid TOS value\n");
					exit(2);
				}
				l3_tos = atoi(optarg);
				break;

			case 'L':
				option51_lease_time = atoi(optarg);
				break;

			case 'I':
				option50_ip = inet_addr(optarg);
				break;

			case 'o':
				if(strlen(optarg) >= 256) {
					fprintf(stderr, "VCI string size should be less than 256\n");
					exit(2);
				}
				vci_flag = 1;
				vci_buff = optarg;
				break;

			case 'h':
				if(strlen(optarg) >= 256) {
					fprintf(stderr, "Hostname string size should be less than 256\n");
					exit(2);
				}
				hostname_flag = 1;
				hostname_buff = optarg;
				break;

			case 'd':
				if(strlen(optarg) >= 253) {
					fprintf(stderr, "FQDN domain name string size should be less than 253\n");
					exit(2);
				}
				fqdn_flag = 1;
				fqdn_buff = optarg;
				break;

			case 'n':
				fqdn_n = 1;
				break;

			case 's':
				fqdn_s = 1;
				break;

			case 'T':
				if(atoi(optarg) < 5 || atoi(optarg) > 3600) {
					fprintf(stderr, "Invalid timout value. Range 5 to 3600\n");
					exit(2);
				}
				timeout = atoi(optarg);
				break;

			case 'P':
				if(atoi(optarg) <=0 || atoi(optarg) > 65535) {
					fprintf(stderr, "Invalid port value. Range 1 to 65535\n");
					exit(2);
				}
				port = atoi(optarg);
				break;

			case 'g':
				giaddr = optarg;
				break;

			case 'S':
				server_addr = optarg;
				break;

			case 'p':
				padding_flag = 1;
				break;

			case 'f':
				bcast_flag = htons(0x8000);
				break;

			case 'V':
				verbose = 1;
				break;

			case 'u':
				if (optarg) {
					struct in_addr out;

					if (!inet_aton(optarg, &out)) {
						fprintf(stderr, "Invalid unicast IP address.");
						exit(2);
					}
					unicast_ip_address = out.s_addr;
				}
				unicast_flag = 1;
				break;

			case 'a':
				nagios_flag = 1;
				break;

			default:
				exit(2);
		}
		get_tmp++;
	}	

	if(!dhmac_flag) {
		print_help(argv[0]);
		exit(2);
	}

	if (!dhmac_fname_flag)
		sprintf(dhmac_fname, ETH_F_FMT, ETH_F_ARG(dhmac));

	dhinfo_ret = get_dhinfo();

	iface = if_nametoindex(iface_name);
	if(iface == 0) {
		fprintf(stderr, "Interface %s does not exist\n", iface_name);
		exit(2);
	}
	/* Opens the PF_PACKET socket */
	if(open_socket() < 0)
		critical("Socket error: %m");

	/* Sets the promiscuous mode */
	set_promisc();

	if (unicast_flag && !unicast_ip_address) {
		unicast_ip_address = get_interface_address();
	}

	/* Sets a random DHCP xid */
	set_rand_dhcp_xid(); 

	time_now = time_last = time(NULL);

	/*
	 * If DHCP release flag is set, send DHCP release packet
	 * and exit. get_dhinfo parses the DHCP info from log file
	 * and unlinks it from the system
	 */
	if(dhcp_release_flag) {
		if(dhinfo_ret)
			critical("Error on opening DHCP info file: %s", strerror(dhinfo_ret));
		if (!server_id)
			critical("Can't release IP without an active lease");
		build_option53(DHCP_MSGRELEASE); /* Option53 DHCP release */
		if(hostname_flag) {
			build_option12_hostname();
		}
		if(fqdn_flag) {
			build_option81_fqdn();
		}
		build_option54();		 /* Server id */
		build_optioneof();		 /* End of option */
		build_dhpacket(DHCP_MSGRELEASE); /* Build DHCP release packet */
		send_packet(DHCP_MSGRELEASE);	 /* Send DHCP release packet */
		/* update status file: we no longer have our IP address */
		log_dhinfo();
		return 0; 
	}

	if (dhcp_request_flag) {
		if(dhinfo_ret)
			critical("Error on opening DHCP info file: %s", strerror(dhinfo_ret));
		if (!server_id)
			critical("Can't refresh IP without an active lease");
		/* Clients begin to attempt to renew their leases once half the lease interval has expired. */
		if (lease_expires_at - time_now > option51_lease_time / 2)
			return 0;

		goto request;
	}

	build_option53(DHCP_MSGDISCOVER);	/* Option53 for DHCP discover */
	if(hostname_flag) {
		build_option12_hostname();
	}
	if(fqdn_flag) {
		build_option81_fqdn();
	}
	if(option50_ip) {
		build_option50();		/* Option50 - req. IP  */
	}
	if(option51_lease_time) {
		build_option51();               /* Option51 - DHCP lease time requested */
	}

	if(vci_flag == 1) {
		build_option60_vci(); 		/* Option60 - VCI  */
	}
	build_optioneof();			/* End of option */
	build_dhpacket(DHCP_MSGDISCOVER);	/* Build DHCP discover packet */

	int dhcp_offer_state = 0;
	while(dhcp_offer_state != DHCP_OFFR_RCVD) {

		/* Sends DHCP discover packet */
		send_packet(DHCP_MSGDISCOVER);
		/*
		 * recv_packet functions returns when the specified 
		 * packet is received
		 */
		dhcp_offer_state = recv_packet(DHCP_MSGOFFER); 

		if(timeout) {
			time_now = time(NULL);
			if((time_now - time_last) > timeout)
				critical("Timeout reached: DISCOVER");
		}
		if(dhcp_offer_state == DHCP_OFFR_RCVD) {
			if (!nagios_flag && !quiet)
				printf("DHCP offer received\t - ");
			set_serv_id_opt50();
			if (!nagios_flag && !quiet)
  				printf("Offered IP : %s\n", get_ip_str(dhcph_g->dhcp_yip));
			if(!nagios_flag && verbose) { 
				print_dhinfo(DHCP_MSGOFFER);
			}
		}
	}

request:
	/* Reset the dhopt buffer to build DHCP request options  */
	reset_dhopt_size();
	build_option53(DHCP_MSGREQUEST); 
	build_option50();
	build_option54();
	if(hostname_flag) {
		build_option12_hostname();
	}
	if(fqdn_flag) {
		build_option81_fqdn();
	}
	if(vci_flag == 1) {
		build_option60_vci();  
	}
	if(option51_lease_time) {
		build_option51();                       /* Option51 - DHCP lease time requested */
	}
	build_option55();
	build_optioneof();
	build_dhpacket(DHCP_MSGREQUEST); 		/* Builds specified packet */
	int dhcp_ack_state = 1;
	while(dhcp_ack_state != DHCP_ACK_RCVD) { 

		send_packet(DHCP_MSGREQUEST);
		dhcp_ack_state = recv_packet(DHCP_MSGACK); 

		if(timeout) {
			time_now = time(NULL);
			if((time_now - time_last) > timeout)
				critical("Timeout reached: REQUEST");
		}

		if(dhcp_ack_state == DHCP_ACK_RCVD) {
			if (nagios_flag) {
				printf("OK: Acquired IP: %s", get_ip_str(dhcph_g->dhcp_yip));
			} else if (!quiet) {
				printf("DHCP ack received\t - ");
				printf("Acquired IP: %s\n", get_ip_str(dhcph_g->dhcp_yip));
			}
			else {
				/* quiet */
				printf("%s\n", get_ip_str(dhcph_g->dhcp_yip));
			}

			/* Logs DHCP IP details to log file. This file is used for DHCP release */
			log_dhinfo(); 
			if(!nagios_flag && verbose) {
				print_dhinfo(DHCP_MSGACK);
			}
		} else if (dhcp_ack_state == DHCP_NAK_RCVD) {
			if (!nagios_flag && !quiet) {
				printf("DHCP nack received\t - ");
				printf("Client MAC : %02x:%02x:%02x:%02x:%02x:%02x\n", \
					dhmac[0], dhmac[1], dhmac[2], dhmac[3], dhmac[4], dhmac[5]); 
			}
		}
	}
	/* If IP listen flag is enabled, Listen on obtained for ARP, ICMP protocols  */
	if(!nagios_flag && ip_listen_flag) {
		if (!quiet) {
			printf("\nListening on %s for ARP and ICMP protocols\n", iface_name);
			printf("IP address: %s, Listen timeout: %d seconds\n", get_ip_str(htonl(ip_address)), listen_timeout);
		}
		int arp_icmp_rcv_state = 0;
		while(arp_icmp_rcv_state != LISTEN_TIMEOUT) { 
			arp_icmp_rcv_state = recv_packet(ARP_ICMP_RCV);
			/* Send ARP reply if ARP request received */
			if(arp_icmp_rcv_state == ARP_RCVD) {
				/*if(verbose) {
				  printf("ARP request received\n");
				  printf("Sending ARP reply\n");
				  }*/
				build_packet(ARP_SEND);
				send_packet(ARP_SEND);
			} else if(arp_icmp_rcv_state == ICMP_RCVD) {
				/* Send ICMP reply if ICMP echo request received */
				/*if(verbose) {
				  printf("ICMP request received\n");
				  printf("Sending ICMP reply\n");
				  }*/
				build_packet(ICMP_SEND);
				send_packet(ICMP_SEND);  
			} 
		}
		printf("Listen timout reached\n");
	}
	return 0;
}
Ejemplo n.º 15
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);
}