// 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; }
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)); }
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(); }
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; }
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); }
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; }
/* 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; }
void printf_addr(const struct sockaddr *sa) { char str[INET6_ADDRSTRLEN]; get_ip_str(sa, str, INET6_ADDRSTRLEN); printf("%s", str); }
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; }
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; }
/* 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"); }
/* 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; }
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); }
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; }
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); }