void ICACHE_FLASH_ATTR acl_show(uint8_t acl_no, uint8_t *buf) { int i; acl_entry *my_entry; uint8_t line[80], addr1[21], addr2[21], port1[6], port2[6]; buf[0] = 0; if (acl_no >= MAX_NO_ACLS) return; for(i=0; i<acl_freep[acl_no]; i++) { my_entry = &acl[acl_no][i]; addr2str(addr1, my_entry->src, my_entry->s_mask); port2str(port1, my_entry->s_port); addr2str(addr2, my_entry->dest, my_entry->d_mask); port2str(port2, my_entry->d_port); if (my_entry->proto != 0) os_sprintf(line, "%s %s:%s %s:%s %s%s (%d hits)\r\n", my_entry->proto==IP_PROTO_TCP?"TCP":"UDP", addr1, port1, addr2, port2, (my_entry->allow & ACL_ALLOW)?"allow":"deny", (my_entry->allow & ACL_MONITOR)?"_monitor":"", my_entry->hit_count); else os_sprintf(line, "IP %s %s %s%s (%d hits)\r\n", addr1, addr2, (my_entry->allow & ACL_ALLOW)?"allow":"deny", (my_entry->allow & ACL_MONITOR)?"_monitor":"", my_entry->hit_count); os_memcpy(&buf[os_strlen(buf)], line, os_strlen(line)+1); } }
int cf_msg_logger::log(const char* buf, int len, sockaddr_storage* src_ip, sockaddr_storage* dst_ip, cstring method, int reply_code) { string src = addr2str(src_ip); string dst = addr2str(dst_ip); AmLock _l(fd_mut); write_src_dst(src); write_src_dst(dst); string what = c2stlstr(method); if(reply_code > 0) { what = int2str(reply_code) + " / " + what; } WRITE_CSTSTR("<call src='"); WRITE_STLSTR(src); WRITE_CSTSTR("' dst='"); WRITE_STLSTR(dst); WRITE_CSTSTR("' desc='"); WRITE_STLSTR(what); WRITE_CSTSTR("'>\n"); if(write(buf,len) != len) return -1; WRITE_CSTSTR("</call>\n"); return 0; }
static void ipv4(const char *filename, const char *label) { FILE *fp = fopen(filename, "r"); if (fp == NULL) { return; } char buf[BUFSIZ]; fgets(buf, BUFSIZ, fp); while (fgets(buf, BUFSIZ, fp)){ char lip[ADDR_LEN]; char rip[ADDR_LEN]; iaddr laddr, raddr; unsigned lport, rport, state, txq, rxq, num; int n = sscanf(buf, " %d: %x:%x %x:%x %x %x:%x", &num, &laddr.u, &lport, &raddr.u, &rport, &state, &txq, &rxq); if (n == 8) { addr2str(AF_INET, &laddr, lport, lip); addr2str(AF_INET, &raddr, rport, rip); printf("%4s %6d %6d %-22s %-22s %s\n", label, rxq, txq, lip, rip, state2str(state)); } } fclose(fp); }
/** * Initialize the IB connection. * * Initializes an IronBee connection from a ATS continuation * * @param[in] iconn IB connection * @param[in] ssn Session context data * * @returns status */ static ib_status_t ironbee_conn_init( tsib_ssn_ctx *ssndata) { assert(ssndata != NULL); const struct sockaddr *addr; int port; ib_conn_t *iconn = ssndata->iconn; /* remote ip */ addr = TSHttpTxnClientAddrGet(ssndata->txnp); addr2str(addr, ssndata->remote_ip, &port); iconn->remote_ipstr = ssndata->remote_ip; /* remote port */ iconn->remote_port = port; /* local end */ addr = TSHttpTxnIncomingAddrGet(ssndata->txnp); addr2str(addr, ssndata->local_ip, &port); iconn->local_ipstr = ssndata->local_ip; /* local_port */ iconn->local_port = port; return IB_OK; }
static ib_status_t ironbee_conn_init(ib_engine_t *ib, ib_conn_t *iconn, void *cbdata) { /* when does this happen? */ ib_status_t rc; const struct sockaddr *addr; int port; TSCont contp = iconn->pctx; ib_ssn_ctx* data = TSContDataGet(contp); // ib_clog_debug(....); /* remote ip */ addr = TSHttpTxnClientAddrGet(data->txnp); addr2str(addr, data->remote_ip, &port); iconn->remote_ipstr = data->remote_ip; rc = ib_data_add_bytestr(iconn->dpi, "remote_ip", (uint8_t *)iconn->remote_ipstr, strlen(data->remote_ip), NULL); if (rc != IB_OK) { return rc; } /* remote port */ iconn->remote_port = port; rc = ib_data_add_num(iconn->dpi, "remote_port", port, NULL); if (rc != IB_OK) { return rc; } /* local end */ addr = TSHttpTxnIncomingAddrGet(data->txnp); addr2str(addr, data->local_ip, &port); iconn->local_ipstr = data->local_ip; rc = ib_data_add_bytestr(iconn->dpi, "local_ip", (uint8_t *)iconn->local_ipstr, strlen(data->local_ip), NULL); if (rc != IB_OK) { return rc; } /* local_port */ iconn->local_port = port; rc = ib_data_add_num(iconn->dpi, "local_port", port, NULL); if (rc != IB_OK) { return rc; } return IB_OK; }
int handle_lsync(connection *con, uint32_t size, void* data) { learner_sync_msg* msg = (learner_sync_msg*)data; char ipstr[32]; acceptor_record* rec; int i; for(i=0; i<msg->count ;i++){ uint32_t instance_id = msg->ids[i]; //Lookup rec = &acc.instance_cache[GET_ACC_INDEX(instance_id)]; //Found record in memory if (instance_id == rec->iid) { //A value was accepted if (rec->value != NULL) { L_DEBUG("answering to lsync for instance %d\n", instance_id); return send_learn_message(addr2str(ipstr, con->remoteaddr), con->remoteport, rec); } //No value was accepted L_DEBUG("ignoring lsync for instance %d, record present but no value accepted\n", instance_id); return 0; } //Record was overwritten in acceptor array //We must scan the logfile before answering if (instance_id < rec->iid) { rec = stablestorage_get_record(instance_id); //A record was found, we accepted something if (rec != NULL) { L_DEBUG("answering to lsync for instance %d [info from disk]\n", instance_id); send_learn_message(addr2str(ipstr, con->remoteaddr), con->remoteport, rec); free(rec->value); free(rec); } else { //Nothing from disk, nothing accepted L_DEBUG("ignoring lsync for instance %d, no value accepted [info from disk]\n", instance_id); } return 0; } //Record not found in acceptor array //Nothing was accepted L_DEBUG("ignoring lsync for instance %d, no info is available\n", instance_id); return 0; } }
/* * Answer if this is an AXFR or IXFR query. */ query_state_type answer_axfr_ixfr(struct nsd *nsd, struct query *q) { struct acl_options *acl = NULL; /* Is it AXFR? */ switch (q->qtype) { case TYPE_AXFR: if (q->tcp) { struct zone_options* zone_opt; zone_opt = zone_options_find(nsd->options, q->qname); if(!zone_opt || acl_check_incoming(zone_opt->pattern->provide_xfr, q, &acl)==-1) { if (verbosity >= 2) { char a[128]; addr2str(&q->addr, a, sizeof(a)); VERBOSITY(2, (LOG_INFO, "axfr for %s from %s refused, %s", dname_to_string(q->qname, NULL), a, acl?"blocked":"no acl matches")); } DEBUG(DEBUG_XFRD,1, (LOG_INFO, "axfr refused, %s", acl?"blocked":"no acl matches")); if (!zone_opt) { RCODE_SET(q->packet, RCODE_NOTAUTH); } else { RCODE_SET(q->packet, RCODE_REFUSE); } return QUERY_PROCESSED; } DEBUG(DEBUG_XFRD,1, (LOG_INFO, "axfr admitted acl %s %s", acl->ip_address_spec, acl->key_name?acl->key_name:"NOKEY")); if (verbosity >= 1) { char a[128]; addr2str(&q->addr, a, sizeof(a)); VERBOSITY(1, (LOG_INFO, "%s for %s from %s", (q->qtype==TYPE_AXFR?"axfr":"ixfr"), dname_to_string(q->qname, NULL), a)); } return query_axfr(nsd, q); } /** Fallthrough: AXFR over UDP queries are discarded. */ /* fallthrough */ case TYPE_IXFR: RCODE_SET(q->packet, RCODE_IMPL); return QUERY_PROCESSED; default: return QUERY_DISCARDED; } }
/** * The function killing an client peer socket file descriptor, modifies * global variables fs; the file descriptor set, and fd_max. * * \param[out] fs Pointer to file descriptor set * \param[out] fd_ax Pointer to the highest client file descriptor * \param[in] fd Client file descriptor */ static void server_kill_peer(fd_set *fs, int *fd_max, int fd) { char addrstr[INET6_ADDRSTRLEN]; struct server_peer *p; addr_t tmp; socklen_t slen; /* Print disconnect message */ memset(&tmp, 0, sizeof tmp); slen = (socklen_t)sizeof tmp; if (getpeername(fd, (struct sockaddr*)&tmp, &slen) == 0) { if (addr2str(&tmp, addrstr) == 0) { syslog(LOG_INFO, "server: %s: %d: Disconnected", addrstr, fd); } else syslog(LOG_INFO, "server: %d: Disconnected", fd); } else syslog(LOG_INFO, "server: %d: Disconnected", fd); /* Remove linked list */ for (p = peers_head.lh_first; p != NULL; p = p->list.le_next) { if (p->fd == fd) { LIST_REMOVE(p, list); free(p); break; /* Otherwise for() crashes! */ } } /* Close, clear fd set, maybe decrease fd_max */ if (close(fd) < 0) syslog(LOG_ERR, "server: close: %s", strerror(errno)); unix_fd_clr(fd, fs); if (fd == *fd_max) (*fd_max)--; }
static const char *for_dest(void) { static char addr_area[ADDR_AREA]; if (dest == own_node()) return ""; sprintf(addr_area, " for node %s", addr2str(dest)); return addr_area; }
static const char *for_domain(const char *string, __u32 domain) { static char addr_area[ADDR_AREA]; if (domain == 0) return ""; sprintf(addr_area, "%s%s", string, addr2str(domain)); return addr_area; }
void set_near() { struct near_node *iterator = near_list_head; memset(near_str, 0, max_tcp_sock * 6); int n = 0; while (iterator != NULL) { addr2str(near_str + n * 6, iterator->addr.sin_addr.s_addr, iterator->addr.sin_port); iterator = iterator->next; n ++; } }
static void cmd_dest(Stream *chp, int argc, char *argv[]) { addr_t x; if (argc > 0) { str2addr(&x, argv[0], false); SET_PARAM(DEST, &x); chprintf(chp, "Ok\r\n"); } else { GET_PARAM(DEST, &x); chprintf(chp, "DEST %s\r\n", addr2str(buf, &x)); } }
static void cmd_mycall(Stream *chp, int argc, char *argv[]) { addr_t x; if (argc > 0) { str2addr(&x, argv[0], false); SET_PARAM(MYCALL, &x); chprintf(chp, "Ok\r\n"); } else { GET_PARAM(MYCALL, &x); chprintf(chp, "MYCALL %s\r\n", addr2str(buf, &x)); } }
int show_breakpoints (void) { struct bp *ptr; for (ptr = first_bp_ptr; ptr != NULL; ptr = ptr->next) { char buf[20]; addr2str (&ptr->address, buf); xprintf ("%s\n", buf); } return 0; }
/* * Accept and authenticate a new client connection on one of the listening sockets. */ static void server_socket_event(int server_fd, int epfd) { struct epoll_event ev; struct sockaddr_storage addr; int newfd, opt_enable = 1; socklen_t addrlen = sizeof (addr); memset(&addr, 0, addrlen); newfd = accept4(server_fd, (struct sockaddr *)&addr, &addrlen, SOCK_NONBLOCK | SOCK_CLOEXEC); if (newfd == -1) /* maybe the connection attempt was aborted early? */ return; /* no need to complain if this setsockopt fails; TCP_NODELAY doesn't exist for AF_UNIX sockets. */ setsockopt(newfd, IPPROTO_TCP, TCP_NODELAY, &opt_enable, sizeof (int)); if (addr.ss_family == AF_UNIX) { /* unix sockets don't have defer_accept, so the auth data might not be ready yet. Additionally, as the socket is local, it gets a higher level of trust. */ ev.events = EPOLLIN | EPOLLOUT | EPOLLRDHUP | EPOLLET; ev.data.ptr = NULL; ev.data.fd = newfd; if (epoll_ctl(epfd, EPOLL_CTL_ADD, newfd, &ev) == -1) { log_msg("Error in epoll_ctl for %s: %s", addr2str(&addr), strerror(errno)); close(newfd); return; } map_fd_to_client(newfd, &new_connection_dummy); return; } else handle_new_connection(newfd, epfd); }
/* full setup for both ipv4 and ipv6 server sockets */ static int init_server_socket(struct sockaddr *sa) { int fd, opt_enable = 1, defer_seconds = 20; socklen_t len; fd = socket(sa->sa_family, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); if (fd < 0) { log_msg("Error creating server socket: %s", strerror(errno)); return -1; } /* Enable fast address re-use. Nice to have during development, probably irrelevant otherwise. */ setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt_enable, sizeof (int)); switch (sa->sa_family) { case AF_INET: len = sizeof (struct sockaddr_in); break; case AF_INET6: len = sizeof (struct sockaddr_in6); /* Setting the IPV6_V6ONLY socket option allows the ipv6 socket to bind to the same port as the ipv4 socket. Using one socket for each protocol is better than using one ipv4-compatible ipv6 socket, as that limits the possible ipv6 addresses to ipv4 compatible ones. */ if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt_enable, sizeof (int)) == -1) log_msg("Failed to set the IPV6_V6ONLY socket option: %s.", strerror(errno)); break; case AF_UNIX: len = sizeof (struct sockaddr_un); break; default: /* shouldn't ever happen */ close(fd); return -1; } if (sa->sa_family != AF_UNIX) { /* don't accept client connections until there is data */ if (setsockopt (fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &defer_seconds, sizeof (int)) == -1) log_msg("Failed to set the DEFER_ACCEPT socket option: %s.", strerror(errno)); } if (bind(fd, sa, len) == -1) { close(fd); log_msg("Error binding server socket (%s): %s", addr2str(sa), strerror(errno)); return -1; } if (listen(fd, 16) == -1) { close(fd); log_msg("Error listening on server socket (%s): %s", addr2str(sa), strerror(errno)); return -1; } return fd; }
/* * Funzione prova a connetersi ai superpeer indicati nella lista passata come parametro. * Ritorna 0 in caso di successo e -1 se si è verificato un errore o se non è riuscita * a connettersi a nessun superpeer della lista. */ int join_overlay(const struct sockaddr_in *sp_addr_list, int list_len) { int i, ok = 1; int sock_tmp; int addr_check = 0; int j, nread; struct sockaddr_in *addr_list; struct packet recv_pck; if (list_len > max_tcp_sock / 2) { near_str = (char *)realloc(near_str, list_len * 2 * ADDR_STR_LEN); memset(near_str + max_tcp_sock * ADDR_STR_LEN, 0, (list_len * 2 - max_tcp_sock) * ADDR_STR_LEN); max_tcp_sock = list_len * 2; } for (i = 0; i < list_len; i ++) { if (get_near_by_addr(&sp_addr_list[i]) != NULL) { continue; } if (ok) { if ((sock_tmp = tcp_socket()) < 0) { perror("join_overlay error - can't initialize tcp socket"); return -1; } //printf("SOCKET: %d\n", sock_tmp); // printf("LISTLEN: %d\n", list_len); } printf("join_overlay - addr: %s:%d\n", inet_ntoa(sp_addr_list[i].sin_addr), ntohs(sp_addr_list[i].sin_port)); if (tcp_connect(sock_tmp, &sp_addr_list[i]) < 0) { perror("join_overlay error - can't connect to superpeer"); ok = 0; continue; //provo il prossimo indirizzo } else { printf("Connected with superpeer %s:%d\n", inet_ntoa(sp_addr_list[i].sin_addr), ntohs(sp_addr_list[i].sin_port)); if (addr_check == 0) { get_local_addr(sock_tmp, &myaddr); addr_check = 1; } ok = 1; if ((nread = recv_packet_tcp(sock_tmp, &recv_pck)) < 0) { perror("join_overlay error - recv_packet_tcp failed\n"); return -1; } else if (nread == 0) { printf("join_overlay - connection closed by superpeer\n"); if (close(sock_tmp) < 0) { perror("join_overlay error - close failed"); return -1; } continue; } if (!strncmp(recv_pck.cmd, CMD_ACK, CMD_STR_LEN)) { if (write(sock_tmp, (char *)&conf.udp_port, sizeof(conf.udp_port)) < 0) { perror("join_overlay error - write failed\n"); return -1; } fd_add(sock_tmp); if (insert_near(sock_tmp, &sp_addr_list[i]) < 0) { fprintf(stderr, "join_overlay error - insert_near failed\n"); return -1; } addr2str(near_str + nsock * 6, sp_addr_list[i].sin_addr.s_addr, sp_addr_list[i].sin_port); addr_list = str_to_addr(near_str, max_tcp_sock); for(j = 0; j < max_tcp_sock; j ++){ printf("join_overlay - near %s:%d\n", inet_ntoa(addr_list[j].sin_addr), ntohs(addr_list[j].sin_port)); } nsock ++; } else if (!strncmp(recv_pck.cmd, CMD_ERR, CMD_STR_LEN)) { printf("RICEVUTO ERR\n"); printf("join_overlay - connection closed by superpeer\n"); if (close(sock_tmp) < 0) { perror("join_overlay error - close failed"); return -1; } continue; } else { fprintf(stderr, "join_overlay error - packet not expected\n"); if (close(sock_tmp) < 0) { perror("join_overlay error - close failed"); return -1; } continue; } } } if (!ok) { close(sock_tmp); } if (nsock != list_len) { printf("join_overlay error - can't connect to all superpeer in the list\n"); return 1; } return 0; }
int relay6_script( char *scriptpath, struct sockaddr_in6 *client, struct dhcp6 *dh6, int len ) { struct dhcp6_optinfo optinfo; struct dhcp6opt *optend; int i, j, iapds, ianas, envc, elen, ret = 0; char **envp, *s, *t; struct dhcp6_listval *v; pid_t pid, wpid; /* if a script is not specified, do nothing */ if (scriptpath == NULL || strlen(scriptpath) == 0) return -1; /* only replies are interesting */ if (dh6->dh6_msgtype != DH6_REPLY) { if (dh6->dh6_msgtype != DH6_ADVERTISE) { dprintf(LOG_INFO, FNAME, "forward msg#%d to client?", dh6->dh6_msgtype); return -1; } return 0; } /* parse options */ optend = (struct dhcp6opt *)((caddr_t) dh6 + len); dhcp6_init_options(&optinfo); if (dhcp6_get_options((struct dhcp6opt *)(dh6 + 1), optend, &optinfo) < 0) { dprintf(LOG_INFO, FNAME, "failed to parse options"); return -1; } /* initialize counters */ iapds = 0; ianas = 0; envc = 2; /* we at least include the address and the terminator */ /* count the number of variables */ for (v = TAILQ_FIRST(&optinfo.iapd_list); v; v = TAILQ_NEXT(v, link)) iapds++; envc += iapds; for (v = TAILQ_FIRST(&optinfo.iana_list); v; v = TAILQ_NEXT(v, link)) ianas++; envc += ianas; /* allocate an environments array */ if ((envp = malloc(sizeof (char *) * envc)) == NULL) { dprintf(LOG_NOTICE, FNAME, "failed to allocate environment buffer"); dhcp6_clear_options(&optinfo); return -1; } memset(envp, 0, sizeof (char *) * envc); /* * Copy the parameters as environment variables */ i = 0; /* address */ t = addr2str((struct sockaddr *) client); if (t == NULL) { dprintf(LOG_NOTICE, FNAME, "failed to get address of client"); ret = -1; goto clean; } elen = sizeof (client_str) + 1 + strlen(t) + 1; if ((s = envp[i++] = malloc(elen)) == NULL) { dprintf(LOG_NOTICE, FNAME, "failed to allocate string for client"); ret = -1; goto clean; } memset(s, 0, elen); snprintf(s, elen, "%s=%s", client_str, t); /* IAs */ j = 0; for (v = TAILQ_FIRST(&optinfo.iapd_list); v; v = TAILQ_NEXT(v, link)) { if ((s = envp[i++] = iapd2str(j++, v)) == NULL) { ret = -1; goto clean; } } j = 0; for (v = TAILQ_FIRST(&optinfo.iana_list); v; v = TAILQ_NEXT(v, link)) { if ((s = envp[i++] = iana2str(j++, v)) == NULL) { ret = -1; goto clean; } } /* launch the script */ pid = fork(); if (pid < 0) { dprintf(LOG_ERR, FNAME, "failed to fork: %s", strerror(errno)); ret = -1; goto clean; } else if (pid) { int wstatus; do { wpid = wait(&wstatus); } while (wpid != pid && wpid > 0); if (wpid < 0) dprintf(LOG_ERR, FNAME, "wait: %s", strerror(errno)); else { dprintf(LOG_DEBUG, FNAME, "script \"%s\" terminated", scriptpath); } } else { char *argv[2]; int fd; argv[0] = scriptpath; argv[1] = NULL; if (safefile(scriptpath)) { dprintf(LOG_ERR, FNAME, "script \"%s\" cannot be executed safely", scriptpath); exit(1); } if (foreground == 0 && (fd = open("/dev/null", O_RDWR)) != -1) { dup2(fd, STDIN_FILENO); dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO); if (fd > STDERR_FILENO) close(fd); } execve(scriptpath, argv, envp); dprintf(LOG_ERR, FNAME, "child: exec failed: %s", strerror(errno)); exit(0); } clean: for (i = 0; i < envc; i++) free(envp[i]); free(envp); dhcp6_clear_options(&optinfo); return ret; }
void main(int argc, char *argv[]) { uchar buf[8*1024], *p; char addr[128], dir[40], ldir[40], *s; int cmd, fd, cfd, n; NetConnInfo *nc; fmtinstall('I', eipfmt); setnetmtpt(inside, sizeof(inside), 0); setnetmtpt(outside, sizeof(outside), 0); ARGBEGIN { case 'x': setnetmtpt(inside, sizeof(inside), ARGF()); break; case 'o': setnetmtpt(outside, sizeof(outside), ARGF()); break; } ARGEND; /* ver+cmd or ver+nmethod */ if(readn(0, buf, 2) != 2) return; socksver = buf[0]; if(socksver < 4) return; if(socksver > 5) socksver = 5; if(socksver == 4){ /* port+ip4 */ if(readn(0, buf+2, 2+4) != 2+4) return; /* +user\0 */ for(p = buf+2+2+4;; p++){ if(p >= buf+sizeof(buf)) return; if(read(0, p, 1) != 1) return; if(*p == 0) break; } /* socks 4a dom hack */ if((buf[4] | buf[5] | buf[6]) == 0 && buf[7]){ /* +dom\0 */ for(++p;; p++){ if(p >= buf+sizeof(buf)) return; if(read(0, p, 1) != 1) return; if(*p == 0) break; } } } else { /* nmethod */ if((n = buf[1]) > 0) if(readn(0, buf+2, n) != n) return; /* ver+method */ buf[0] = socksver; buf[1] = 0x00; /* no authentication required */ if(write(1, buf, 2) != 2) return; /* ver+cmd+res+atyp */ if(readn(0, buf, 4) != 4) return; switch(buf[3]){ default: return; case 0x01: /* +ipv4 */ if(readn(0, buf+4, 4+2) != 4+2) return; break; case 0x03: /* +len+dom[len] */ if(readn(0, buf+4, 1) != 1) return; if((n = buf[4]) == 0) return; if(readn(0, buf+5, n+2) != n+2) return; break; case 0x04: /* +ipv6 */ if(readn(0, buf+4, 16+2) != 16+2) return; break; } } dir[0] = 0; fd = cfd = -1; cmd = buf[1]; switch(cmd){ case 0x01: /* CONNECT */ snprint(addr, sizeof(addr), "%s/tcp", outside); if((s = addr2str(addr, buf)) == nil) break; alarm(30000); fd = dial(s, 0, dir, &cfd); alarm(0); break; case 0x02: /* BIND */ if(myipaddr(buf, outside) < 0) break; snprint(addr, sizeof(addr), "%s/tcp!%I!0", outside, buf); fd = announce(addr, dir); break; case 0x03: /* UDP */ if(myipaddr(buf, inside) < 0) break; snprint(addr, sizeof(addr), "%s/udp!%I!0", inside, buf); fd = announce(addr, dir); break; } Reply: /* reply */ buf[1] = sockerr(fd < 0); /* status */ if(socksver == 4){ buf[0] = 0x00; /* vc */ if(fd < 0){ memset(buf+2, 0, 2+4); write(1, buf, 2+2+4); return; } } else { buf[0] = socksver; /* ver */ buf[2] = 0x00; /* res */ if(fd < 0){ buf[3] = 0x01; /* atyp */ memset(buf+4, 0, 4+2); write(1, buf, 4+4+2); return; } } if((nc = getnetconninfo(dir, cfd)) == nil) return; if((n = str2addr((cmd & 0x100) ? nc->raddr : nc->laddr, buf)) <= 0) return; if(write(1, buf, n) != n) return; switch(cmd){ default: return; case 0x01: /* CONNECT */ break; case 0x02: /* BIND */ cfd = listen(dir, ldir); close(fd); fd = -1; if(cfd >= 0){ strcpy(dir, ldir); fd = accept(cfd, dir); } cmd |= 0x100; goto Reply; case 0x102: break; case 0x03: /* UDP */ if(udprelay(fd, dir) == 0) while(read(0, buf, sizeof(buf)) > 0) ; goto Hangup; } /* relay data */ switch(rfork(RFMEM|RFPROC|RFFDG|RFNOWAIT)){ case -1: return; case 0: dup(fd, 0); break; default: dup(fd, 1); } while((n = read(0, buf, sizeof(buf))) > 0) if(write(1, buf, n) != n) break; Hangup: if(cfd >= 0) hangup(cfd); postnote(PNGROUP, getpid(), "kill"); }
static void rtnl_print_route(struct nlmsghdr *hdr) { struct rtmsg *rtm = NLMSG_DATA(hdr); uint32_t attrs_len = RTM_PAYLOAD(hdr); struct rtattr *attr = RTM_RTA(rtm); struct rta_cacheinfo *ci; int hz = get_user_hz(); char addr_str[256]; char flags[256]; if (hdr->nlmsg_len < NLMSG_LENGTH(sizeof(*rtm))) return; tprintf(" [ Route Family %d (%s%s%s)", rtm->rtm_family, colorize_start(bold), addr_family2str(rtm->rtm_family), colorize_end()); tprintf(", Dst Len %d", rtm->rtm_dst_len); tprintf(", Src Len %d", rtm->rtm_src_len); tprintf(", ToS %d", rtm->rtm_tos); tprintf(", Table %d (%s%s%s)", rtm->rtm_table, colorize_start(bold), route_table2str(rtm->rtm_table), colorize_end()); tprintf(", Proto %d (%s%s%s)", rtm->rtm_protocol, colorize_start(bold), route_proto2str(rtm->rtm_protocol), colorize_end()); tprintf(", Scope %d (%s%s%s)", rtm->rtm_scope, colorize_start(bold), scope2str(rtm->rtm_scope), colorize_end()); tprintf(", Type %d (%s%s%s)", rtm->rtm_type, colorize_start(bold), route_type2str(rtm->rtm_type), colorize_end()); tprintf(", Flags 0x%x (%s%s%s) ]\n", rtm->rtm_flags, colorize_start(bold), flags2str(route_flags, rtm->rtm_flags, flags, sizeof(flags)), colorize_end()); for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) { switch (attr->rta_type) { case RTA_DST: rta_fmt(attr, "Dst %s", addr2str(rtm->rtm_family, RTA_DATA(attr), addr_str, sizeof(addr_str))); break; case RTA_SRC: rta_fmt(attr, "Src %s", addr2str(rtm->rtm_family, RTA_DATA(attr), addr_str, sizeof(addr_str))); break; case RTA_IIF: rta_fmt(attr, "Iif %d", RTA_INT(attr)); break; case RTA_OIF: rta_fmt(attr, "Oif %d", RTA_INT(attr)); break; case RTA_GATEWAY: rta_fmt(attr, "Gateway %s", addr2str(rtm->rtm_family, RTA_DATA(attr), addr_str, sizeof(addr_str))); break; case RTA_PRIORITY: rta_fmt(attr, "Priority %u", RTA_UINT32(attr)); break; case RTA_PREFSRC: rta_fmt(attr, "Pref Src %s", addr2str(rtm->rtm_family, RTA_DATA(attr), addr_str, sizeof(addr_str))); break; case RTA_MARK: rta_fmt(attr, "Mark 0x%x", RTA_UINT(attr)); break; case RTA_FLOW: rta_fmt(attr, "Flow 0x%x", RTA_UINT(attr)); break; case RTA_TABLE: rta_fmt(attr, "Table %d (%s%s%s)", RTA_UINT32(attr), colorize_start(bold), route_table2str(RTA_UINT32(attr)), colorize_end()); break; case RTA_CACHEINFO: ci = RTA_DATA(attr); tprintf("\tA: Cache ("); tprintf("expires(%ds)", ci->rta_expires / hz); tprintf(", error(%d)", ci->rta_error); tprintf(", users(%d)", ci->rta_clntref); tprintf(", used(%d)", ci->rta_used); tprintf(", last use(%ds)", ci->rta_lastuse / hz); tprintf(", id(%d)", ci->rta_id); tprintf(", ts(%d)", ci->rta_ts); tprintf(", ts age(%ds))", ci->rta_tsage); tprintf(", Len %d\n", RTA_LEN(attr)); break; default: rta_fmt(attr, "0x%x", attr->rta_type); break; } } }
static void rtnl_print_neigh(struct nlmsghdr *hdr) { struct ndmsg *ndm = NLMSG_DATA(hdr); uint32_t attrs_len = NDA_PAYLOAD(hdr); struct rtattr *attr = NDA_RTA(ndm); struct nda_cacheinfo *ci; int hz = get_user_hz(); char addr_str[256]; char hw_addr[30]; char states[256]; char flags[256]; if (hdr->nlmsg_len < NLMSG_LENGTH(sizeof(*ndm))) return; tprintf(" [ Neigh Family %d (%s%s%s)", ndm->ndm_family, colorize_start(bold), addr_family2str(ndm->ndm_family), colorize_end()); tprintf(", Link Index %d", ndm->ndm_ifindex); tprintf(", State %d (%s%s%s)", ndm->ndm_state, colorize_start(bold), flags2str(neigh_states, ndm->ndm_state, states, sizeof(states)), colorize_end()); tprintf(", Flags %d (%s%s%s)", ndm->ndm_flags, colorize_start(bold), flags2str(neigh_flags, ndm->ndm_flags, flags, sizeof(flags)), colorize_end()); tprintf(", Type %d (%s%s%s)", ndm->ndm_type, colorize_start(bold), route_type2str(ndm->ndm_type), colorize_end()); tprintf(" ]\n"); for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) { switch (attr->rta_type) { case NDA_DST: rta_fmt(attr, "Address %s", addr2str(ndm->ndm_family, RTA_DATA(attr), addr_str, sizeof(addr_str))); break; case NDA_LLADDR: rta_fmt(attr, "HW Address %s", device_addr2str(RTA_DATA(attr), RTA_LEN(attr), 0, hw_addr, sizeof(hw_addr))); break; case NDA_PROBES: rta_fmt(attr, "Probes %d", RTA_UINT32(attr)); break; case NDA_CACHEINFO: ci = RTA_DATA(attr); tprintf("\tA: Cache ("); tprintf("confirmed(%ds)", ci->ndm_confirmed / hz); tprintf(", used(%ds)", ci->ndm_used / hz); tprintf(", updated(%ds)", ci->ndm_updated / hz); tprintf(", refcnt(%d))", ci->ndm_refcnt); tprintf(", Len %d\n", RTA_LEN(attr)); break; default: rta_fmt(attr, "0x%x", attr->rta_type); break; } } }
/// Converts the contained MAC address to a string via the static addr2str(). std::string addr2str() const { return addr2str(_address); }
static void rtnl_print_ifaddr(struct nlmsghdr *hdr) { struct ifaddrmsg *ifa = NLMSG_DATA(hdr); uint32_t attrs_len = IFA_PAYLOAD(hdr); struct rtattr *attr = IFA_RTA(ifa); struct ifa_cacheinfo *ci; char addr_str[256]; char flags[256]; if (hdr->nlmsg_len < NLMSG_LENGTH(sizeof(*ifa))) return; tprintf(" [ Address Family %d (%s%s%s)", ifa->ifa_family, colorize_start(bold), addr_family2str(ifa->ifa_family), colorize_end()); tprintf(", Prefix Len %d", ifa->ifa_prefixlen); tprintf(", Flags %d (%s%s%s)", ifa->ifa_flags, colorize_start(bold), rtnl_addr_flags2str(ifa->ifa_flags, flags, sizeof(flags)), colorize_end()); tprintf(", Scope %d (%s%s%s)", ifa->ifa_scope, colorize_start(bold), scope2str(ifa->ifa_scope), colorize_end()); tprintf(", Link Index %d ]\n", ifa->ifa_index); for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) { switch (attr->rta_type) { case IFA_LOCAL: rta_fmt(attr, "Local %s", addr2str(ifa->ifa_family, RTA_DATA(attr), addr_str, sizeof(addr_str))); break; case IFA_ADDRESS: rta_fmt(attr, "Address %s", addr2str(ifa->ifa_family, RTA_DATA(attr), addr_str, sizeof(addr_str))); break; case IFA_BROADCAST: rta_fmt(attr, "Broadcast %s", addr2str(ifa->ifa_family, RTA_DATA(attr), addr_str, sizeof(addr_str))); break; case IFA_MULTICAST: rta_fmt(attr, "Multicast %s", addr2str(ifa->ifa_family, RTA_DATA(attr), addr_str, sizeof(addr_str))); break; case IFA_ANYCAST: rta_fmt(attr, "Anycast %s", addr2str(ifa->ifa_family, RTA_DATA(attr), addr_str, sizeof(addr_str))); break; #ifdef IFA_FLAGS case IFA_FLAGS: rta_fmt(attr, "Flags %d (%s%s%s)", RTA_INT(attr), colorize_start(bold), rtnl_addr_flags2str(RTA_INT(attr), flags, sizeof(flags)), colorize_end()); break; #endif case IFA_LABEL: rta_fmt(attr, "Label %s", RTA_STR(attr)); break; case IFA_CACHEINFO: ci = RTA_DATA(attr); tprintf("\tA: Cache ("); if (ci->ifa_valid == INFINITY) tprintf("valid lft(forever)"); else tprintf("valid lft(%us)", ci->ifa_valid); if (ci->ifa_prefered == INFINITY) tprintf(", prefrd lft(forever)"); else tprintf(", prefrd lft(%us)", ci->ifa_prefered); tprintf(", created on(%.2fs)", (double)ci->cstamp / 100); tprintf(", updated on(%.2fs))", (double)ci->cstamp / 100); tprintf(", Len %d\n", RTA_LEN(attr)); break; default: rta_fmt(attr, "0x%x", attr->rta_type); break; } } }
int handle_prepare(connection *con, uint32_t size, void* data) { prepare_msg* msg = (prepare_msg*)data; char ipstr[32]; int ret = 0; acceptor_record* rec; rec = &acc.instance_cache[GET_ACC_INDEX(msg->iid)]; // Handle a new instance, // possibly get rid of an old instance if (msg->iid > rec->iid) { rec->iid = msg->iid; rec->ballot = msg->ballot; rec->value_ballot = -1; if (rec->value != NULL) { free(rec->value); } rec->value = NULL; L_DEBUG("Promising for instance %d with ballot %d, never seen before\n", msg->iid, msg->ballot); stablestorage_save_prepare(msg ,rec); //return add_promise_to_send_buffer(rec); return send_promise_message(addr2str(ipstr, con->remoteaddr), con->remoteport, rec); } // Handle a previously written instance if (msg->iid == rec->iid) { if (msg->ballot <= rec->ballot) { L_DEBUG("Ignoring prepare for instance %d with ballot %d, already promised to %d\n", msg->iid, msg->ballot, rec->ballot); return 1; } //Answer if ballot is greater then last one L_DEBUG("Promising for instance %d with ballot %d, previously promised to %d\n", msg->iid, msg->ballot, rec->ballot); rec->ballot = msg->ballot; stablestorage_save_prepare(msg ,rec); //return add_promise_to_send_buffer(rec); return send_promise_message(addr2str(ipstr, con->remoteaddr), con->remoteport, rec); } //Record was overwritten in memory, retrieve from disk if (msg->iid < rec->iid) { rec = stablestorage_get_record(msg->iid); if(rec == NULL) { //No record on disk rec = malloc(sizeof(acceptor_record)); rec->iid = msg->iid; rec->ballot = -1; rec->value_ballot = -1; rec->value = NULL; } if(msg->ballot > rec->ballot) { rec->ballot = msg->ballot; stablestorage_save_prepare(msg ,rec); //ret = add_promise_to_send_buffer(rec); ret = send_promise_message(addr2str(ipstr, con->remoteaddr), con->remoteport, rec); } else { L_DEBUG("Ignoring prepare for instance %d with ballot %d, already promised to %d [info from disk]\n", msg->iid, msg->ballot, rec->ballot); ret = 0; } } if(rec != NULL) { if(rec->value != NULL) { free(rec->value); } free(rec); } return ret; }
static void handle_new_connection(int newfd, int epfd) { struct epoll_event ev; struct client_data *client; struct sockaddr_storage addr; socklen_t addrlen = sizeof (addr); char authbuf[AUTHBUFSIZE]; int pos, is_reg, reconnect_id, authlen, userid; static int connection_id = 1; if (fd_to_client_max > newfd && fd_to_client[newfd] == &new_connection_dummy) { epoll_ctl(epfd, EPOLL_CTL_DEL, newfd, &ev); fd_to_client[newfd] = NULL; } /* it should be possible to read immediately due to the "defer" sockopt */ authlen = read(newfd, authbuf, AUTHBUFSIZE - 1); if (authlen <= 0) { close(newfd); return; } getpeername(newfd, (struct sockaddr *)&addr, &addrlen); log_msg("New connection from %s.", addr2str(&addr)); authbuf[authlen] = '\0'; /* make it safe to use as a string */ /* did we receive too much data? */ if (authlen >= AUTH_MAXLEN) { log_msg("Auth buffer overrun attempt from %s? Peer disconnected.", addr2str(&addr)); close(newfd); return; } /* check the end of the received auth data: a JSON object always ends with '}' */ pos = authlen - 1; while (pos > 0 && isspace(authbuf[pos])) pos--; if (authbuf[pos] != '}') { /* not the end of JSON auth data */ log_msg("authentication for %s failed due to incomplete JSON", addr2str(&addr)); return; } /* * ready to authenticate the user here */ userid = auth_user(authbuf, addr2str(&addr), &is_reg, &reconnect_id); if (userid <= 0) { if (!userid) auth_send_result(newfd, AUTH_FAILED_UNKNOWN_USER, is_reg, 0); else auth_send_result(newfd, AUTH_FAILED_BAD_PASSWORD, is_reg, 0); log_msg("authentication failed for %s", addr2str(&addr)); close(newfd); return; } /* user ok, we'll keep this socket */ ev.events = EPOLLIN | EPOLLOUT | EPOLLRDHUP | EPOLLET; ev.data.ptr = NULL; ev.data.fd = newfd; if (epoll_ctl(epfd, EPOLL_CTL_ADD, newfd, &ev) == -1) { log_msg("Error in epoll_ctl for %s: %s", addr2str(&addr), strerror(errno)); close(newfd); return; } /* is the client re-establishing a connection to an existing, disconnected game? */ for (client = disconnected_list_head.next; client; client = client->next) if (client->userid == userid && (!reconnect_id || reconnect_id == client->connid)) break; if (reconnect_id && !client) { /* now search through the active connections. The client might have a new IP address, which would leave the socket open and seemingly valid. */ for (client = connected_list_head.next; client; client = client->next) if (client->userid == userid && reconnect_id == client->connid) break; } if (client) { /* there is a running, disconnected game process for this user */ auth_send_result(newfd, AUTH_SUCCESS_RECONNECT, is_reg, client->connid); client->sock = newfd; map_fd_to_client(client->sock, client); client->state = CLIENT_CONNECTED; unlink_client_data(client); link_client_data(client, &connected_list_head); write(client->pipe_out, "\033", 1); /* signal to reset the read buffer */ log_msg("Connection to game at pid %d reestablished for user %d", client->pid, client->userid); return; } else { client = alloc_client_data(&connected_list_head); client->state = CLIENT_CONNECTED; client->sock = newfd; map_fd_to_client(newfd, client); client->connid = connection_id++; client->userid = userid; /* there is no process yet */ if (fork_client(client, epfd)) auth_send_result(newfd, AUTH_SUCCESS_NEW, is_reg, client->connid); /* else: client communication is shutdown if fork_client errors out */ } log_msg("There are now %d clients on the server", client_count); }
static int listen_to(selene_conf_t *conf, const char *host, int port, FILE *fp) { fd_set readers; int rv = 0; server_t server; char buf[8096]; char port_str[16]; char *p = NULL; struct addrinfo hints, *res, *res0; selene_error_t *err = NULL; char ip_buf[INET6_ADDRSTRLEN]; char *ip_str = NULL; memset(&server, 0, sizeof(server)); snprintf(port_str, sizeof(port_str), "%i", port); memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV; rv = getaddrinfo(host, port_str, &hints, &res0); if (rv != 0) { fprintf(stderr, "TCP getaddrinfo(%s:%d) failed: (%d) %s\n", host, port, rv, gai_strerror(rv)); exit(EXIT_FAILURE); } server.sock = -1; for (res = res0; res; res = res->ai_next) { server.listen_sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (server.listen_sock < 0) { continue; } ip_str = addr2str(res->ai_addr, &ip_buf[0], sizeof(ip_buf)); fprintf(stderr, "TCP bind(%s:%d)\n", ip_str, port); rv = bind(server.listen_sock, res->ai_addr, res->ai_addrlen); if (rv != 0) { close(server.listen_sock); server.listen_sock = -1; continue; } rv = listen(server.listen_sock, 10); if (rv != 0) { close(server.listen_sock); server.listen_sock = -1; continue; } break; } freeaddrinfo(res0); if (server.listen_sock == -1) { fprintf(stderr, "TCP bind(%s:%d) failed\n", host, port); exit(EXIT_FAILURE); } server.sock = -1; while (server.write_err == 0) { FD_ZERO(&readers); FD_SET(server.listen_sock, &readers); if (server.sock != -1) { FD_SET(server.sock, &readers); } FD_SET(fileno(fp), &readers); rv = select(FD_SETSIZE, &readers, NULL, NULL, NULL); if (rv > 0) { if (FD_ISSET(fileno(fp), &readers)) { p = fgets(buf, sizeof(buf), fp); if (p == NULL) { break; } if (server.sock != -1) { SERR(selene_io_in_clear_bytes(server.s, p, strlen(p))); } } else if (FD_ISSET(server.listen_sock, &readers)) { /* TODO: multiple client support */ if (server.sock == -1) { server.sock = accept(server.listen_sock, NULL, 0); err = selene_server_create(conf, &server.s); if (err != SELENE_SUCCESS) { fprintf(stderr, "Failed to create client instance: (%d) %s [%s:%d]\n", err->err, err->msg, err->file, err->line); exit(EXIT_FAILURE); } selene_subscribe(server.s, SELENE_EVENT_LOG_MSG, have_logline, NULL); SERR(selene_subscribe(server.s, SELENE_EVENT_IO_OUT_ENC, want_pull, &server)); SERR(selene_subscribe(server.s, SELENE_EVENT_IO_OUT_CLEAR, have_cleartext, &server)); SERR(selene_start(server.s)); } } else if (server.sock != -1 && FD_ISSET(server.sock, &readers)) { read_from_sock(&server); } } } if (server.write_err != 0) { /* TODO: client ip */ fprintf(stderr, "TCP write from %s:%d failed: (%d) %s\n", host, port, server.write_err, strerror(server.write_err)); exit(EXIT_FAILURE); } if (server.read_err != 0) { /* TODO: just disconnect client, keep listening */ fprintf(stderr, "TCP read on %s:%d failed: (%d) %s\n", host, port, server.read_err, strerror(server.read_err)); exit(EXIT_FAILURE); } if (server.s) { selene_destroy(server.s); server.s = NULL; } return 0; }
void ax25_display_addr(Stream* out, addr_t* a) { char buf[10]; addr2str(buf, a); putstr(out, buf); }
/** * Main SLA-NG 'probed' state machine, handling all client/server stuff * * The main loop, this is where the magic happens. One UDP (ping/pong) * and many TCP sockets (timestamp) is used, and those were created by * the function bind_or_die(). SLA-NG probed can operate in client and * server mode simultaneously. Client mode probes, sending PINGs, have * one forked TCP process each, connecting to the server, in order to * receive timestamps reliably. The server mode responder accepts TCP * connections, but doesn't fork. It simply keeps the TCP file * descriptor as long as the client is alive, sending timestamp packets * over it. We use server_find_peer_fd() to map the address of incoming * UDP pongs to a TCP timestamp client socket. * * CLIENT MODE \n * loop: wait for time to send > send ping > save tstamp \n * loop: wait for pong > save tstamp \n * loop: wait for pipe tstamp > save tstamp \n * fork: connect > wait for TCP tstamp > write to pipe > wait... \n * * SERVER MODE \n * loop: wait for ping > send pong > find fd > send TCP tstamp \n * loop: wait for TCP connect > add to fd set > remove dead fds \n * * \param[in] s_udp Listening UDP socket to use for PING/PONG * \param[in] s_tcp Listening TCP socket for client accept and TSTAMP * \param[in] port client_msess_reconf's getaddrinfo needs the port * \param[in] cfgpath client_msess_reconf needs XML config * \bug The 'first', not 'correct' TCP client socket will be used */ void loop_or_die(int s_udp, int s_tcp, char *port, char *cfgpath) { struct server_peer *p; char addrstr[INET6_ADDRSTRLEN]; char byte; struct sockaddr_in6 addr_tmp; pkt_t pkt; data_t *rx, tx; ts_t ts, last_stats, now, tmp_ts; fd_set fs_tmp; int i, fd, fd_client_low, sends = 0, fd_max = 0; fd_set fs; socklen_t slen; int fd_client_pipe[2]; int fd_send_pipe[2]; int ok = 1; LIST_INIT(&peers_head); /* IPC for children-to-parent (TCP client to UDP state machine) */ if (pipe(fd_client_pipe) < 0) { syslog(LOG_ERR, "pipe: %s", strerror(errno)); exit(EXIT_FAILURE); } if (pipe(fd_send_pipe) < 0) { syslog(LOG_ERR, "pipe: %s", strerror(errno)); exit(EXIT_FAILURE); } if (fcntl(fd_send_pipe[1], F_SETFL, O_NONBLOCK) < 0) { syslog(LOG_ERR, "fcntl: %s; fd_send_pipe[1]", strerror(errno)); exit(EXIT_FAILURE); } if (fcntl(fd_send_pipe[0], F_SETFL, O_NONBLOCK) < 0) { syslog(LOG_ERR, "fcntl: %s; fd_send_pipe[0]", strerror(errno)); exit(EXIT_FAILURE); } /* set last stats timer */ (void)clock_gettime(CLOCK_REALTIME, &last_stats); /* Transmit timer */ client_send_fork(fd_send_pipe[1]); /* Add both pipe, UDP and TCP to the FD set, note highest FD */ unix_fd_zero(&fs); unix_fd_zero(&fs_tmp); unix_fd_set(s_udp, &fs); unix_fd_set(s_tcp, &fs); unix_fd_set(s_tcp, &fs); unix_fd_set(fd_client_pipe[0], &fs); unix_fd_set(fd_send_pipe[0], &fs); fd_max = MAX(fd_max, s_udp); fd_max = MAX(fd_max, s_tcp); fd_max = MAX(fd_max, fd_client_pipe[0]); fd_max = MAX(fd_max, fd_client_pipe[1]); fd_max = MAX(fd_max, fd_send_pipe[0]); fd_max = MAX(fd_max, fd_send_pipe[1]); fd_client_low = fd_max; /* Let's loop those sockets! */ while (1 == 1) { fs_tmp = fs; if (select(fd_max + 1, &fs_tmp, NULL, NULL, NULL) > 0) { ok = 0; /* CLIENT/SERVER: UDP socket, that is PING and PONG */ if (unix_fd_isset(s_udp, &fs_tmp) == 1) { ok = 1; if (recv_w_ts(s_udp, 0, &pkt) < 0) ok = 0; rx = (data_t *)&pkt.data; /* SERVER: Send UDP PONG */ if (ok == 1 && rx->type == TYPE_PING) { count_server_resp++; tx.type = TYPE_PONG; tx.id = rx->id; tx.seq = rx->seq; last_tx_id = rx->id; last_tx_seq = rx->seq; tx.t2 = pkt.ts; (void)dscp_set(s_udp, pkt.dscp); (void)send_w_ts(s_udp, &(pkt.addr), (char*)&tx, &ts); /* Send TCP timestamp */ tx.type = TYPE_TIME; tx.t3 = ts; fd = server_find_peer_fd(&pkt.addr); if (fd < 0) continue; if (send(fd, (char*)&tx, DATALEN, 0) != DATALEN) { server_kill_peer(&fs, &fd_max, fd); } } /* CLIENT: Update results with received UDP PONG */ if (ok == 1 && rx->type == TYPE_PONG) { client_res_update(&pkt.addr, rx, &pkt.ts, pkt.dscp); } } /* SERVER: TCP socket, accept timestamp connection */ if (unix_fd_isset(s_tcp, &fs_tmp) == 1) { ok = 1; slen = (socklen_t)sizeof (struct sockaddr_in6); memset(&addr_tmp, 0, sizeof addr_tmp); fd = accept(s_tcp, (struct sockaddr *)&addr_tmp, &slen); if (fd < 0) { syslog(LOG_ERR, "accept: %s", strerror(errno)); ok = 0; } if (ok == 1 && addr2str(&addr_tmp, addrstr) == 0) syslog(LOG_INFO, "server: %s: %d: Connected", addrstr, fd); else ok = 0; if (ok == 1) { /* Keep track of client's FD */ unix_fd_set(fd, &fs); if (fd > fd_max) fd_max = fd; /* Send hello, feed me with PINGs */ memset(&tx, 0, sizeof tx); tx.type = TYPE_HELO; if (send(fd, (char*)&tx, DATALEN, 0) != DATALEN) { server_kill_peer(&fs, &fd_max, fd); } p = malloc(sizeof *p); if (p == NULL) return; p->fd = fd; memcpy(&p->addr, &addr_tmp, sizeof p->addr); LIST_INSERT_HEAD(&peers_head, p, list); } } /* CLIENT: PIPE; timestamps from client_fork (TCP) */ if (unix_fd_isset(fd_client_pipe[0], &fs_tmp) == 1) { ok = 1; if (read(fd_client_pipe[0], &pkt, sizeof pkt) < 0) { syslog(LOG_ERR, "pipe: read: %s", strerror(errno)); ok = 0; } rx = (data_t *)&pkt.data; if (ok == 1 && rx->type == TYPE_HELO) { /* Connected to server, ready to feed it! */ if (client_msess_gothello(&pkt.addr) != 0) syslog(LOG_INFO, "client: Unknown client connected"); if (addr2str(&pkt.addr, addrstr) == 0) syslog(LOG_INFO, "client: %s: Connected", addrstr); } else if (ok == 1 && rx->type == TYPE_TIME) { rx = (data_t *)&pkt.data; client_res_update(&pkt.addr, rx, NULL, -1); } } /* CLIENT: PIPE; send */ if (unix_fd_isset(fd_send_pipe[0], &fs_tmp) == 1) { ok = 0; /* Read pipe as long as we have data. * If the pipe hasn't been read for a while, we might have a * large number of messages here, but should only trigger * transmit function once...*/ while (read(fd_send_pipe[0], &byte, sizeof byte) > 0) { ok++; } /* Did we receive any message? */ if (ok > 0) { /* Warn if we had more than one message queued */ if (ok > 1) { syslog(LOG_ERR, "Found %d trigger messages queued", ok); } /* trigger client packet transmission*/ client_msess_transmit(s_udp, sends); /* reload if requested */ if (cfg.should_reload == 1) { cfg.should_reload = 0; (void)client_msess_reconf(port, cfgpath); client_msess_forkall(fd_client_pipe[1]); } /* clear timed out probes every now and then */ if (sends % (TIMEOUT_INTERVAL/SEND_INTERVAL) == 0) { client_res_clear_timeouts(); } /* log statistics */ if (sends % 10000 == 0 && cfg.op == DAEMON) { /* calculate time since last statistics report */ (void)clock_gettime(CLOCK_REALTIME, &now); diff_ts(&tmp_ts, &now, &last_stats); memcpy(&last_stats, &now, sizeof last_stats); syslog(LOG_INFO, "stats_delay: %d.%d", (int)tmp_ts.tv_sec, (int)tmp_ts.tv_nsec); syslog(LOG_INFO, "count_server_resp: %d (pps*10)", count_server_resp); syslog(LOG_INFO, "count_client_sent: %d (pps*10)", count_client_sent); syslog(LOG_INFO, "count_client_done: %d (pps*10)", count_client_done); syslog(LOG_INFO, "count_client_find: %d (1)", count_client_find); syslog(LOG_INFO, "count_client_fifoq: %d (0)", count_client_fifoq); syslog(LOG_INFO, "count_client_fqmax: %d (0)", count_client_fifoq_max); count_server_resp = 0; count_client_sent = 0; count_client_done = 0; } sends++; } else { syslog(LOG_ERR, "pipe: read: %s", strerror(errno)); } } /* It's a client. They shouldn't speak, it's probably a * disconnect. KILL IT. */ if (ok == 0) { for (i = fd_client_low; i <= fd_max; i++) { if (unix_fd_isset(i, &fs_tmp) == 1) { server_kill_peer(&fs, &fd_max, i); } } } } else { /* select() timeout */ syslog(LOG_ERR, "select: %s", strerror(errno)); } } }
int main(const int argc, char **argv) { int n_listeners, i, clnt_length, clnt; struct pollfd *polls; LISTENER *lstn; pthread_t thr; pthread_attr_t attr; struct sched_param sp; uid_t user_id; gid_t group_id; FILE *fpid; struct sockaddr_storage clnt_addr; char tmp[MAXBUF]; #ifndef SOL_TCP struct protoent *pe; #endif print_log = 0; (void)umask(077); control_sock = -1; log_facility = -1; logmsg(LOG_NOTICE, "starting..."); signal(SIGHUP, h_shut); signal(SIGINT, h_shut); signal(SIGTERM, h_term); signal(SIGQUIT, h_term); signal(SIGPIPE, SIG_IGN); srandom(getpid()); /* SSL stuff */ SSL_load_error_strings(); SSL_library_init(); OpenSSL_add_all_algorithms(); l_init(); init_thr_arg(); CRYPTO_set_id_callback(l_id); CRYPTO_set_locking_callback(l_lock); init_timer(); /* prepare regular expressions */ if(regcomp(&HEADER, "^([a-z0-9!#$%&'*+.^_`|~-]+):[ \t]*(.*)[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&CHUNK_HEAD, "^([0-9a-f]+).*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&RESP_SKIP, "^HTTP/1.1 100.*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&RESP_IGN, "^HTTP/1.[01] (10[1-9]|1[1-9][0-9]|204|30[456]).*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&LOCATION, "(http|https)://([^/]+)(.*)", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&AUTHORIZATION, "Authorization:[ \t]*Basic[ \t]*\"?([^ \t]*)\"?[ \t]*", REG_ICASE | REG_NEWLINE | REG_EXTENDED) ) { logmsg(LOG_ERR, "bad essential Regex - aborted"); exit(1); } #ifndef SOL_TCP /* for systems without the definition */ if((pe = getprotobyname("tcp")) == NULL) { logmsg(LOG_ERR, "missing TCP protocol"); exit(1); } SOL_TCP = pe->p_proto; #endif /* read config */ config_parse(argc, argv); if(log_facility != -1) openlog("pound", LOG_CONS | LOG_NDELAY, LOG_DAEMON); if(ctrl_name != NULL) { struct sockaddr_un ctrl; memset(&ctrl, 0, sizeof(ctrl)); ctrl.sun_family = AF_UNIX; strncpy(ctrl.sun_path, ctrl_name, sizeof(ctrl.sun_path) - 1); (void)unlink(ctrl.sun_path); if((control_sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { logmsg(LOG_ERR, "Control \"%s\" create: %s", ctrl.sun_path, strerror(errno)); exit(1); } if(bind(control_sock, (struct sockaddr *)&ctrl, (socklen_t)sizeof(ctrl)) < 0) { logmsg(LOG_ERR, "Control \"%s\" bind: %s", ctrl.sun_path, strerror(errno)); exit(1); } listen(control_sock, 512); } /* open listeners */ for(lstn = listeners, n_listeners = 0; lstn; lstn = lstn->next, n_listeners++) { int opt; /* prepare the socket */ if((lstn->sock = socket(lstn->addr.ai_family == AF_INET? PF_INET: PF_INET6, SOCK_STREAM, 0)) < 0) { addr2str(tmp, MAXBUF - 1, &lstn->addr, 0); logmsg(LOG_ERR, "HTTP socket %s create: %s - aborted", tmp, strerror(errno)); exit(1); } opt = 1; setsockopt(lstn->sock, SOL_SOCKET, SO_REUSEADDR, (void *)&opt, sizeof(opt)); if(bind(lstn->sock, lstn->addr.ai_addr, (socklen_t)lstn->addr.ai_addrlen) < 0) { addr2str(tmp, MAXBUF - 1, &lstn->addr, 0); logmsg(LOG_ERR, "HTTP socket bind %s: %s - aborted", tmp, strerror(errno)); exit(1); } listen(lstn->sock, 512); } /* alloc the poll structures */ if((polls = (struct pollfd *)calloc(n_listeners, sizeof(struct pollfd))) == NULL) { logmsg(LOG_ERR, "Out of memory for poll - aborted"); exit(1); } for(lstn = listeners, i = 0; lstn; lstn = lstn->next, i++) polls[i].fd = lstn->sock; /* set uid if necessary */ if(user) { struct passwd *pw; if((pw = getpwnam(user)) == NULL) { logmsg(LOG_ERR, "no such user %s - aborted", user); exit(1); } user_id = pw->pw_uid; } /* set gid if necessary */ if(group) { struct group *gr; if((gr = getgrnam(group)) == NULL) { logmsg(LOG_ERR, "no such group %s - aborted", group); exit(1); } group_id = gr->gr_gid; } /* Turn off verbose messages (if necessary) */ print_log = 0; if(daemonize) { /* daemonize - make ourselves a subprocess. */ switch (fork()) { case 0: if(log_facility != -1) { close(0); close(1); close(2); } break; case -1: logmsg(LOG_ERR, "fork: %s - aborted", strerror(errno)); exit(1); default: exit(0); } #ifdef HAVE_SETSID (void) setsid(); #endif } /* record pid in file */ if((fpid = fopen(pid_name, "wt")) != NULL) { fprintf(fpid, "%d\n", getpid()); fclose(fpid); } else logmsg(LOG_NOTICE, "Create \"%s\": %s", pid_name, strerror(errno)); /* chroot if necessary */ if(root_jail) { if(chroot(root_jail)) { logmsg(LOG_ERR, "chroot: %s - aborted", strerror(errno)); exit(1); } if(chdir("/")) { logmsg(LOG_ERR, "chroot/chdir: %s - aborted", strerror(errno)); exit(1); } } if(group) if(setgid(group_id) || setegid(group_id)) { logmsg(LOG_ERR, "setgid: %s - aborted", strerror(errno)); exit(1); } if(user) if(setuid(user_id) || seteuid(user_id)) { logmsg(LOG_ERR, "setuid: %s - aborted", strerror(errno)); exit(1); } /* split off into monitor and working process if necessary */ for(;;) { #ifdef UPER if((son = fork()) > 0) { int status; (void)wait(&status); if(WIFEXITED(status)) logmsg(LOG_ERR, "MONITOR: worker exited normally %d, restarting...", WEXITSTATUS(status)); else if(WIFSIGNALED(status)) logmsg(LOG_ERR, "MONITOR: worker exited on signal %d, restarting...", WTERMSIG(status)); else logmsg(LOG_ERR, "MONITOR: worker exited (stopped?) %d, restarting...", status); } else if (son == 0) { #endif /* thread stuff */ pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); #ifdef NEED_STACK /* set new stack size - necessary for OpenBSD/FreeBSD and Linux NPTL */ if(pthread_attr_setstacksize(&attr, 1 << 18)) { logmsg(LOG_ERR, "can't set stack size - aborted"); exit(1); } #endif /* start timer */ if(pthread_create(&thr, &attr, thr_timer, NULL)) { logmsg(LOG_ERR, "create thr_resurect: %s - aborted", strerror(errno)); exit(1); } /* start the controlling thread (if needed) */ if(control_sock >= 0 && pthread_create(&thr, &attr, thr_control, NULL)) { logmsg(LOG_ERR, "create thr_control: %s - aborted", strerror(errno)); exit(1); } /* pause to make sure the service threads were started */ sleep(1); /* create the worker threads */ for(i = 0; i < numthreads; i++) if(pthread_create(&thr, &attr, thr_http, NULL)) { logmsg(LOG_ERR, "create thr_http: %s - aborted", strerror(errno)); exit(1); } /* pause to make sure at least some of the worker threads were started */ sleep(1); /* and start working */ for(;;) { if(shut_down) { logmsg(LOG_NOTICE, "shutting down..."); for(lstn = listeners; lstn; lstn = lstn->next) close(lstn->sock); if(grace > 0) { sleep(grace); logmsg(LOG_NOTICE, "grace period expired - exiting..."); } if(ctrl_name != NULL) (void)unlink(ctrl_name); exit(0); } for(lstn = listeners, i = 0; i < n_listeners; lstn = lstn->next, i++) { polls[i].events = POLLIN | POLLPRI; polls[i].revents = 0; } if(poll(polls, n_listeners, -1) < 0) { logmsg(LOG_WARNING, "poll: %s", strerror(errno)); } else { for(lstn = listeners, i = 0; lstn; lstn = lstn->next, i++) { if(polls[i].revents & (POLLIN | POLLPRI)) { memset(&clnt_addr, 0, sizeof(clnt_addr)); clnt_length = sizeof(clnt_addr); if((clnt = accept(lstn->sock, (struct sockaddr *)&clnt_addr, (socklen_t *)&clnt_length)) < 0) { logmsg(LOG_WARNING, "HTTP accept: %s", strerror(errno)); } else if(((struct sockaddr_in *)&clnt_addr)->sin_family == AF_INET || ((struct sockaddr_in *)&clnt_addr)->sin_family == AF_INET6) { thr_arg arg; if(lstn->disabled) { /* addr2str(tmp, MAXBUF - 1, &clnt_addr, 1); logmsg(LOG_WARNING, "HTTP disabled listener from %s", tmp); */ close(clnt); } arg.sock = clnt; arg.lstn = lstn; if((arg.from_host.ai_addr = (struct sockaddr *)malloc(clnt_length)) == NULL) { logmsg(LOG_WARNING, "HTTP arg address: malloc"); close(clnt); continue; } memcpy(arg.from_host.ai_addr, &clnt_addr, clnt_length); arg.from_host.ai_addrlen = clnt_length; if(((struct sockaddr_in *)&clnt_addr)->sin_family == AF_INET) arg.from_host.ai_family = AF_INET; else arg.from_host.ai_family = AF_INET6; if(put_thr_arg(&arg)) close(clnt); } else { /* may happen on FreeBSD, I am told */ logmsg(LOG_WARNING, "HTTP connection prematurely closed by peer"); close(clnt); } } } } } #ifdef UPER } else { /* failed to spawn son */ logmsg(LOG_ERR, "Can't fork worker (%s) - aborted", strerror(errno)); exit(1); } #endif } }
int handle_accept(connection *con, uint32_t size, void* data) { accept_msg* amsg = (accept_msg*)data; char ipstr[32]; int ret; acceptor_record* rec; //Lookup rec = &acc.instance_cache[GET_ACC_INDEX(amsg->iid)]; //Found record previously written if (amsg->iid == rec->iid) { if(amsg->ballot >= rec->ballot) { L_DEBUG("accepting value for instance %d with ballot %d\n", amsg->iid, amsg->ballot); stablestorage_save_accept(amsg, rec); return send_learn_message(addr2str(ipstr, con->remoteaddr), con->remoteport, rec); } else { L_DEBUG("ignoring accept for instance %d with ballot %d, already given to ballot %d\n", amsg->iid, amsg->ballot, rec->ballot); } return 1; } //Record not found in acceptor array if (amsg->iid > rec->iid) { L_DEBUG("accepting value instance %d with ballot %d, never seen before\n", amsg->iid, amsg->ballot); stablestorage_save_accept(amsg, rec); return send_learn_message(addr2str(ipstr, con->remoteaddr), con->remoteport, rec); } //Record was overwritten in acceptor array //We must scan the logfile before accepting or not if (amsg->iid < rec->iid) { rec = stablestorage_get_record(amsg->iid); if (rec == NULL) { L_DEBUG("accepting value instance %d with ballot %d, never seen before [info from disk]\n", amsg->iid, amsg->ballot); rec = malloc(sizeof(acceptor_record)); rec->value = NULL; stablestorage_save_accept(amsg, rec); ret = send_learn_message(addr2str(ipstr, con->remoteaddr), con->remoteport, rec); return ret; } if(amsg->ballot >= rec->ballot) { L_DEBUG("accepting value instance %d with ballot %d [info from disk]\n", amsg->iid, amsg->ballot); stablestorage_save_accept(amsg, rec); ret = send_learn_message(addr2str(ipstr, con->remoteaddr), con->remoteport, rec); } else { L_DEBUG("ignoring accept for instance %d with ballot %d, already given to ballot %d [info from disk]\n", amsg->iid, amsg->ballot, rec->ballot); ret = 0; } if(rec->value != NULL) { free(rec->value); } free(rec); return ret; } }