/* only for debugging, it helds the lock too long for "production" use */ void dst_blst_debug(rpc_t* rpc, void* ctx) { int h; struct dst_blst_entry* e; ticks_t now; struct ip_addr ip; if (!cfg_get(core, core_cfg, use_dst_blacklist)){ rpc->fault(ctx, 500, "dst blacklist support disabled"); return; } now=get_ticks_raw(); for(h=0; h<DST_BLST_HASH_SIZE; h++){ LOCK_BLST(h); for(e=dst_blst_hash[h].first; e; e=e->next){ dst_blst_entry2ip(&ip, e); rpc->add(ctx, "ssddd", get_proto_name(e->proto), ip_addr2a(&ip), e->port, (s_ticks_t)(now-e->expire)<=0? TICKS_TO_S(e->expire-now): -TICKS_TO_S(now-e->expire) , e->flags); } UNLOCK_BLST(h); } }
void RuleDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { QStyleOptionViewItemV4 o = option; o.text = index.model()->data(index, Qt::DisplayRole).toString(); o.displayAlignment = Qt::AlignCenter; int column = index.model()->headerData(index.column(),Qt::Horizontal,bfmodel::IdRole).toInt(); // if (index.column() < 6) o.state = QStyle::State_ReadOnly; QVariantList l = index.model()->data(index, bfmodel::DirtyRole).toList(); if (l.contains(column)) o.font.setBold(true); int value = index.model()->data(index, Qt::DisplayRole).toInt(); switch(column) { case bfmodel::SRCIP: if(value ==0) o.text = "ALL"; else o.text = QHostAddress(static_cast<quint32>(value)).toString(); break; case bfmodel::SRCPORT: if(value ==0) o.text = "ALL"; break; case bfmodel::DSTIP: if(value ==0) o.text = "ALL"; else o.text = QHostAddress(static_cast<quint32>(value)).toString(); break; case bfmodel::DSTPORT: if(value ==0) o.text = "ALL"; break; case bfmodel::PROTO: o.text = get_proto_name(value); break; case bfmodel::CHAIN: o.text = get_chain_name(static_cast<bf_chain_t>(value)); break; case bfmodel::POLICY: o.text = get_policy_name(static_cast<bf_policy_t>(value)); break; case bfmodel::OFF: o.text = get_sw_name(static_cast<bf_switch_rules_t>(value)); break; } QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &o, painter); }
/* dumps the content of the blacklist in a human-readable format */ void dst_blst_view(rpc_t* rpc, void* ctx) { int h; int expires; struct dst_blst_entry* e; ticks_t now; struct ip_addr ip; if (!cfg_get(core, core_cfg, use_dst_blacklist)){ rpc->fault(ctx, 500, "dst blacklist support disabled"); return; } now=get_ticks_raw(); for(h=0; h<DST_BLST_HASH_SIZE; h++) { LOCK_BLST(h); for(e=dst_blst_hash[h].first; e; e=e->next) { expires = (s_ticks_t)(now-e->expire)<=0? TICKS_TO_S(e->expire-now): -TICKS_TO_S(now-e->expire); /* don't include expired entries into view report */ if (expires < 0) { continue; } dst_blst_entry2ip(&ip, e); rpc->printf(ctx, "{\n protocol: %s", get_proto_name(e->proto)); rpc->printf(ctx, " ip: %s", ip_addr2a(&ip)); rpc->printf(ctx, " port: %d", e->port); rpc->printf(ctx, " expires in (s): %d", expires); rpc->printf(ctx, " flags: %d\n}", e->flags); } UNLOCK_BLST(h); } }
static void open_sockets(char *cachefilename) { int cachefile; unsigned int buffer[3]; int bytesread = -1; unsigned int nr_sockets = 0; cachefile = open(cachefilename, O_RDONLY); if (cachefile < 0) return; while (bytesread != 0) { unsigned int family, type, protocol; bytesread = read(cachefile, buffer, sizeof(int) * 3); if (bytesread == 0) break; family = buffer[0]; type = buffer[1]; protocol = buffer[2]; printf("family:%s type:%s protocol:%s (%u)\n", get_family_name(family), decode_type(type), get_proto_name(family, protocol), protocol); nr_sockets++; } printf("%u entries in socket cachefile.\n", nr_sockets); close(cachefile); }
static int open_socket(unsigned int domain, unsigned int type, unsigned int protocol) { int fd; __unused__ int ret; struct sockaddr *sa = NULL; socklen_t salen; struct sockopt so = { 0, 0, 0, 0 }; fd = socket(domain, type, protocol); if (fd == -1) return fd; shm->sockets[nr_sockets].fd = fd; shm->sockets[nr_sockets].triplet.family = domain; shm->sockets[nr_sockets].triplet.type = type; shm->sockets[nr_sockets].triplet.protocol = protocol; output(2, "fd[%i] = domain:%i (%s) type:0x%x protocol:%i\n", fd, domain, get_proto_name(domain), type, protocol); /* Set some random socket options. */ sso_socket(&shm->sockets[nr_sockets].triplet, &so, fd); nr_sockets++; /* Sometimes, listen on created sockets. */ if (rand_bool()) { /* fake a sockaddr. */ generate_sockaddr((struct sockaddr **) &sa, (socklen_t *) &salen, domain); ret = bind(fd, sa, salen); /* if (ret == -1) debugf("bind: %s\n", strerror(errno)); else debugf("bind: success!\n"); */ ret = listen(fd, (rand() % 2) + 1); /* if (ret == -1) debugf("listen: %s\n", strerror(errno)); else debugf("listen: success!\n"); */ } /* If we didn't have a function for this sockaddr type, we would * have returned page_rand, so don't free() it or we segv. */ if (sa == (struct sockaddr *) page_rand) return fd; if (sa != NULL) free(sa); return fd; }
void print_all_socket_lists() { struct socket_info *si; struct socket_info** list; unsigned short proto; proto=PROTO_UDP; do{ list=get_sock_info_list(proto); for(si=list?*list:0; si; si=si->next){ printf(" %s: %s [%s]:%s%s\n", get_proto_name(proto), si->name.s, si->address_str.s, si->port_no_str.s, si->flags & SI_IS_MCAST ? " mcast" : ""); } }while((proto=next_proto(proto))); }
//----------------------------------------------- // to_s //----------------------------------------------- char* streamkey_to_s(char *dest, stream_key_t *key) { uint16_t sport, dport; if (0) //pkt_is_v6(pkt)) { sprintf(dest, "IPV6 STREAM HERE"); //sprintf(dest, "%s_%s_%d_%s_%d", get_proto_name(pkt->ip6.ip_p),"?:?:?",sport, "?:?:?", dport); return dest; } else { char leftip[16], rightip[16]; ip2string(leftip, GET_LEFT(key)); ip2string(rightip, GET_RIGHT(key)); sprintf(dest, "%s_%s_%d_%s_%d", get_proto_name(key->v4.ipproto), leftip, key->v4.lport, rightip, key->v4.rport); return dest; } }
static int open_socket(unsigned int domain, unsigned int type, unsigned int protocol) { int fd; struct sockaddr sa; socklen_t salen; fd = socket(domain, type, protocol); if (fd == -1) return fd; shm->socket_fds[nr_sockets] = fd; output(2, "fd[%i] = domain:%i (%s) type:0x%x protocol:%i\n", fd, domain, get_proto_name(domain), type, protocol); nr_sockets++; /* Sometimes, listen on created sockets. */ if (rand() % 2) { __unused__ int ret; /* fake a sockaddr. */ generate_sockaddr((unsigned long *) &sa, (unsigned long *) &salen, domain); ret = bind(fd, &sa, salen); /* if (ret == -1) printf("bind: %s\n", strerror(errno)); else printf("bind: success!\n"); */ ret = listen(fd, (rand() % 2) + 1); /* if (ret == -1) printf("listen: %s\n", strerror(errno)); else printf("listen: success!\n"); */ } return fd; }
/*! * \brief Perform outbound processing - force local socket and set destination URI * \param _m SIP message * \param flow_token string containing the flow-token extracted from the Route: header * \param dst_uri string to write the destination URI to (extracted from flow-token) * \return -1 on error, 0 when outbound not in use, 1 when outbound in use */ static inline int process_outbound(struct sip_msg *_m, str flow_token) { int ret; struct receive_info *rcv = NULL; struct socket_info *si; str dst_uri; if (!rr_obb.decode_flow_token) return 0; ret = rr_obb.decode_flow_token(_m, &rcv, flow_token); if (ret == -2) { LM_DBG("no flow token found - outbound not in use\n"); return 0; } else if (ret == -1) { LM_INFO("failed to decode flow token\n"); return -1; } else if (!ip_addr_cmp(&rcv->src_ip, &_m->rcv.src_ip) || rcv->src_port != _m->rcv.src_port) { LM_DBG("\"incoming\" request found. Using flow-token for" "routing\n"); /* First, force the local socket */ si = find_si(&rcv->dst_ip, rcv->dst_port, rcv->proto); if (si) set_force_socket(_m, si); else { LM_INFO("cannot find socket from flow-token\n"); return -1; } /* Second, override the destination URI */ dst_uri.s = uri_buf; dst_uri.len = 0; dst_uri.len += snprintf(dst_uri.s + dst_uri.len, MAX_ROUTE_URI_LEN - dst_uri.len, "sip:%s", rcv->src_ip.af == AF_INET6 ? "[" : ""); dst_uri.len += ip_addr2sbuf(&rcv->src_ip, dst_uri.s + dst_uri.len, MAX_ROUTE_URI_LEN - dst_uri.len); dst_uri.len += snprintf(dst_uri.s + dst_uri.len, MAX_ROUTE_URI_LEN - dst_uri.len, "%s:%d;transport=%s", rcv->src_ip.af == AF_INET6 ? "]" : "", rcv->src_port, get_proto_name(rcv->proto)); if (set_dst_uri(_m, &dst_uri) < 0) { LM_ERR("failed to set dst_uri\n"); return -1; } ruri_mark_new(); return 1; } LM_DBG("Not using flow-token for routing\n"); return 0; }
static void lock_cachefile(int cachefile, int type) { struct flock fl = { .l_len = 0, .l_start = 0, .l_whence = SEEK_SET, }; fl.l_pid = getpid(); fl.l_type = type; if (verbose) output(2, "waiting on lock for cachefile\n"); if (fcntl(cachefile, F_SETLKW, &fl) == -1) { perror("fcntl F_SETLKW"); exit(1); } if (verbose) output(2, "took lock for cachefile\n"); } static void unlock_cachefile(int cachefile) { struct flock fl = { .l_len = 0, .l_start = 0, .l_whence = SEEK_SET, }; fl.l_pid = getpid(); fl.l_type = F_UNLCK; if (fcntl(cachefile, F_SETLK, &fl) == -1) { perror("fcntl F_UNLCK F_SETLK "); exit(1); } if (verbose) output(2, "dropped lock for cachefile\n"); } static void generate_sockets(void) { int fd, n; int cachefile; unsigned int nr_to_create = NR_SOCKET_FDS; unsigned int buffer[3]; cachefile = creat(cachefilename, S_IWUSR|S_IRUSR); if (cachefile < 0) { outputerr("Couldn't open cachefile for writing! (%s)\n", strerror(errno)); exit(EXIT_FAILURE); } lock_cachefile(cachefile, F_WRLCK); /* * Don't loop forever if all protos all are disabled. */ if (!do_specific_proto) { for (n = 0; n < (int)ARRAY_SIZE(no_protos); n++) { if (!no_protos[n]) break; } if (n >= (int)ARRAY_SIZE(no_protos)) nr_to_create = 0; } while (nr_to_create > 0) { struct socket_triplet st; if (shm->exit_reason != STILL_RUNNING) { close(cachefile); return; } for (st.family = 0; st.family < TRINITY_PF_MAX; st.family++) { if (do_specific_proto == TRUE) st.family = specific_proto; if (get_proto_name(st.family) == NULL) goto skip; BUG_ON(st.family >= ARRAY_SIZE(no_protos)); if (no_protos[st.family]) goto skip; if (sanitise_socket_triplet(&st) == -1) rand_proto_type(&st); fd = open_socket(st.family, st.type, st.protocol); if (fd > -1) { nr_to_create--; buffer[0] = st.family; buffer[1] = st.type; buffer[2] = st.protocol; n = write(cachefile, &buffer, sizeof(int) * 3); if (n == -1) { outputerr("something went wrong writing the cachefile!\n"); exit(EXIT_FAILURE); } if (nr_to_create == 0) goto done; } else { //outputerr("Couldn't open family:%d (%s)\n", st.family, get_proto_name(st.family)); } skip: /* check for ctrl-c */ if (shm->exit_reason != STILL_RUNNING) return; //FIXME: If we've passed -P and we're spinning here without making progress // then we should abort after a few hundred loops. } } done: unlock_cachefile(cachefile); output(1, "created %d sockets\n", nr_sockets); close(cachefile); } void close_sockets(void) { unsigned int i; int fd; int r = 0; struct linger ling = { .l_onoff = FALSE, .l_linger = 0 }; for (i = 0; i < nr_sockets; i++) { //FIXME: This is a workaround for a weird bug where we hang forevre // waiting for bluetooth sockets when we setsockopt. // Hopefully at some point we can remove this when someone figures out what's going on. if (shm->sockets[i].triplet.family == PF_BLUETOOTH) continue; /* Grab an fd, and nuke it before someone else uses it. */ fd = shm->sockets[i].fd; shm->sockets[i].fd = 0; /* disable linger */ r = setsockopt(fd, SOL_SOCKET, SO_LINGER, &ling, sizeof(struct linger)); if (r) perror("setsockopt"); r = shutdown(fd, SHUT_RDWR); if (r) perror("shutdown"); if (close(fd) != 0) output(1, "failed to close socket [%d:%d:%d].(%s)\n", shm->sockets[i].triplet.family, shm->sockets[i].triplet.type, shm->sockets[i].triplet.protocol, strerror(errno)); } nr_sockets = 0; } void open_sockets(void) { int cachefile; unsigned int domain, type, protocol; unsigned int buffer[3]; int bytesread=-1; int fd; cachefile = open(cachefilename, O_RDONLY); if (cachefile < 0) { output(1, "Couldn't find socket cachefile. Regenerating.\n"); generate_sockets(); return; } lock_cachefile(cachefile, F_RDLCK); while (bytesread != 0) { bytesread = read(cachefile, buffer, sizeof(int) * 3); if (bytesread == 0) break; domain = buffer[0]; type = buffer[1]; protocol = buffer[2]; if ((do_specific_proto == TRUE && domain != specific_proto) || (domain < ARRAY_SIZE(no_protos) && no_protos[domain] == TRUE)) { output(1, "ignoring socket cachefile due to specific " "protocol request (or protocol disabled), " "and stale data in cachefile.\n"); regenerate: unlock_cachefile(cachefile); /* drop the reader lock. */ close(cachefile); unlink(cachefilename); generate_sockets(); return; } fd = open_socket(domain, type, protocol); if (fd < 0) { output(1, "Cachefile is stale. Need to regenerate.\n"); close_sockets(); goto regenerate; } /* check for ctrl-c */ if (shm->exit_reason != STILL_RUNNING) { close(cachefile); return; } } if (nr_sockets < NR_SOCKET_FDS) { output(1, "Insufficient sockets in cachefile (%d). Regenerating.\n", nr_sockets); goto regenerate; } output(1, "%d sockets created based on info from socket cachefile.\n", nr_sockets); unlock_cachefile(cachefile); close(cachefile); }
BOOL InsertItemFromStream(HWND hWndListView, t_stream* pt_stream) { LVITEM lvI; int index=ListView_GetItemCount(hWndListView); TCHAR info[128]; t_ether_packet *pt_eth_hdr = (void *)pt_stream->data; // Initialize LVITEM members that are different for each item. { lvI.iItem = index; lvI.iSubItem = 0; lvI.mask = LVIF_TEXT|LVIF_IMAGE; lvI.pszText = TEXT(" "); lvI.iImage = -1; /* 若不要图片,就设置为-1 */ // Insert items into the list. if (ListView_InsertItem(hWndListView, &lvI) == -1) return FALSE; if (pt_stream->selected) ListView_SetCheckState(hwnd_lv, index, 1); lvI.iItem = index; lvI.iSubItem = 1; lvI.mask = LVIF_TEXT|LVIF_IMAGE; lvI.pszText = TEXT(" "); //lvI.pszText = NULL; lvI.iImage = -1; /* 若不要图片,就设置为-1 */ ListView_SetItem(hWndListView, &lvI); #if 0 lvI.iItem = index; lvI.iSubItem = 2; lvI.mask = LVIF_TEXT|LVIF_IMAGE; lvI.pszText = TEXT(" "); //lvI.pszText = NULL; lvI.iImage = -1; /* 若不要图片,就设置为-1 */ ListView_SetItem(hWndListView, &lvI); #else sprintf(info, "%d", index+1); ListView_SetItemText(hWndListView, index, 2, info); #endif ListView_SetItemText(hWndListView, index, 3, pt_stream->name); get_src_addr(info, pt_eth_hdr); ListView_SetItemText(hWndListView, index, 4, info); get_dst_addr(info, pt_eth_hdr); ListView_SetItemText(hWndListView, index, 5, info); get_proto_name(info, pt_eth_hdr); ListView_SetItemText(hWndListView, index, 6, info); sprintf(info, "%d", pt_stream->len); ListView_SetItemText(hWndListView, index, 7, info); get_pkt_desc_info(info, pt_stream->data, pt_stream->err_flags); ListView_SetItemText(hWndListView, index, 8, info); } return TRUE; }
/* fixes a socket list => resolve addresses, * interface names, fills missing members, remove duplicates * fills type_flags if not null with SOCKET_T_IPV4 and/or SOCKET_T_IPV6*/ static int fix_socket_list(struct socket_info **list, int* type_flags) { struct socket_info* si; struct socket_info* l; struct socket_info* next; char* tmp; int len; struct hostent* he; char** h; if (type_flags) *type_flags=0; /* try to change all the interface names into addresses * --ugly hack */ for (si=*list;si;){ next=si->next; if (add_interfaces(si->name.s, AF_INET, si->port_no, si->proto, list)!=-1){ /* success => remove current entry (shift the entire array)*/ sock_listrm(list, si); free_sock_info(si); } si=next; } /* get ips & fill the port numbers*/ #ifdef EXTRA_DEBUG DBG("Listening on \n"); #endif for (si=*list;si;si=si->next){ /* fix port number, port_no should be !=0 here */ if (si->port_no==0){ #ifdef USE_TLS si->port_no= (si->proto==PROTO_TLS)?tls_port_no:port_no; #else si->port_no= port_no; #endif } tmp=int2str(si->port_no, &len); if (len>=MAX_PORT_LEN){ LOG(L_ERR, "ERROR: fix_socket_list: bad port number: %d\n", si->port_no); goto error; } si->port_no_str.s=(char*)pkg_malloc(len+1); if (si->port_no_str.s==0){ LOG(L_ERR, "ERROR: fix_socket_list: out of memory.\n"); goto error; } strncpy(si->port_no_str.s, tmp, len+1); si->port_no_str.len=len; /* get "official hostnames", all the aliases etc. */ he=resolvehost(si->name.s); if (he==0){ LOG(L_ERR, "ERROR: fix_socket_list: could not resolve %s\n", si->name.s); goto error; } /* check if we got the official name */ if (strcasecmp(he->h_name, si->name.s)!=0){ if (add_alias(si->name.s, si->name.len, si->port_no, si->proto)<0){ LOG(L_ERR, "ERROR: fix_socket_list: add_alias failed\n"); } /* change the official name */ pkg_free(si->name.s); si->name.s=(char*)pkg_malloc(strlen(he->h_name)+1); if (si->name.s==0){ LOG(L_ERR, "ERROR: fix_socket_list: out of memory.\n"); goto error; } si->name.len=strlen(he->h_name); strncpy(si->name.s, he->h_name, si->name.len+1); } /* add the aliases*/ for(h=he->h_aliases; h && *h; h++) if (add_alias(*h, strlen(*h), si->port_no, si->proto)<0){ LOG(L_ERR, "ERROR: fix_socket_list: add_alias failed\n"); } hostent2ip_addr(&si->address, he, 0); /*convert to ip_addr format*/ if (type_flags){ *type_flags|=(si->address.af==AF_INET)?SOCKET_T_IPV4:SOCKET_T_IPV6; } if ((tmp=ip_addr2a(&si->address))==0) goto error; si->address_str.s=(char*)pkg_malloc(strlen(tmp)+1); if (si->address_str.s==0){ LOG(L_ERR, "ERROR: fix_socket_list: out of memory.\n"); goto error; } strncpy(si->address_str.s, tmp, strlen(tmp)+1); /* set is_ip (1 if name is an ip address, 0 otherwise) */ si->address_str.len=strlen(tmp); if ( (si->address_str.len==si->name.len)&& (strncasecmp(si->address_str.s, si->name.s, si->address_str.len)==0) ){ si->flags|=SI_IS_IP; /* do rev. DNS on it (for aliases)*/ he=rev_resolvehost(&si->address); if (he==0){ LOG(L_WARN, "WARNING: fix_socket_list:" " could not rev. resolve %s\n", si->name.s); }else{ /* add the aliases*/ if (add_alias(he->h_name, strlen(he->h_name), si->port_no, si->proto)<0){ LOG(L_ERR, "ERROR: fix_socket_list:" "add_alias failed\n"); } for(h=he->h_aliases; h && *h; h++) if (add_alias(*h,strlen(*h),si->port_no,si->proto)<0){ LOG(L_ERR, "ERROR: fix_socket_list:" " add_alias failed\n"); } } } #ifdef USE_MCAST /* Check if it is an multicast address and * set the flag if so */ if (is_mcast(&si->address)) { si->flags |= SI_IS_MCAST; } #endif /* USE_MCAST */ #ifdef EXTRA_DEBUG printf(" %.*s [%s]:%s%s\n", si->name.len, si->name.s, si->address_str.s, si->port_no_str.s, si->flags & SI_IS_MCAST ? " mcast" : ""); #endif } /* removing duplicate addresses*/ for (si=*list;si; si=si->next){ for (l=si->next;l;){ next=l->next; if ((si->port_no==l->port_no) && (si->address.af==l->address.af) && (memcmp(si->address.u.addr, l->address.u.addr, si->address.len) == 0) ){ #ifdef EXTRA_DEBUG printf("removing duplicate %s [%s] == %s [%s]\n", si->name.s, si->address_str.s, l->name.s, l->address_str.s); #endif /* add the name to the alias list*/ if ((!(l->flags& SI_IS_IP)) && ( (l->name.len!=si->name.len)|| (strncmp(l->name.s, si->name.s, si->name.len)!=0)) ) add_alias(l->name.s, l->name.len, l->port_no, l->proto); /* remove l*/ sock_listrm(list, l); free_sock_info(l); } l=next; } } #ifdef USE_MCAST /* Remove invalid multicast entries */ si=*list; while(si){ if ((si->flags & SI_IS_MCAST) && ((si->proto == PROTO_TCP) #ifdef USE_TLS || (si->proto == PROTO_TLS) #endif /* USE_TLS */ )){ LOG(L_WARN, "WARNING: removing entry %s:%s [%s]:%s\n", get_proto_name(si->proto), si->name.s, si->address_str.s, si->port_no_str.s); l = si; si=si->next; sock_listrm(list, l); free_sock_info(l); } else { si=si->next; } } #endif /* USE_MCAST */ return 0; error: return -1; }
static void lock_cachefile(int cachefile, int type) { struct flock fl = { .l_len = 0, .l_start = 0, .l_whence = SEEK_SET, }; fl.l_pid = getpid(); fl.l_type = type; if (verbose) output(2, "waiting on lock for cachefile\n"); if (fcntl(cachefile, F_SETLKW, &fl) == -1) { perror("fcntl F_SETLKW"); exit_main_fail(); } if (verbose) output(2, "took lock for cachefile\n"); } static void unlock_cachefile(int cachefile) { struct flock fl = { .l_len = 0, .l_start = 0, .l_whence = SEEK_SET, }; fl.l_pid = getpid(); fl.l_type = F_UNLCK; if (fcntl(cachefile, F_SETLK, &fl) == -1) { perror("fcntl F_UNLCK F_SETLK "); exit_main_fail(); } if (verbose) output(2, "dropped lock for cachefile\n"); } static unsigned int valid_proto(unsigned int family) { const char *famstr; famstr = get_proto_name(family); /* Not used for creating sockets. */ if (strncmp(famstr, "PF_UNSPEC", 9) == 0) return FALSE; if (strncmp(famstr, "PF_BRIDGE", 9) == 0) return FALSE; if (strncmp(famstr, "PF_SECURITY", 11) == 0) return FALSE; /* Not actually implemented (or now removed). */ if (strncmp(famstr, "PF_NETBEUI", 10) == 0) return FALSE; if (strncmp(famstr, "PF_ASH", 6) == 0) return FALSE; if (strncmp(famstr, "PF_ECONET", 9) == 0) return FALSE; if (strncmp(famstr, "PF_SNA", 6) == 0) return FALSE; if (strncmp(famstr, "PF_WANPIPE", 10) == 0) return FALSE; /* Needs root. */ if (orig_uid != 0) { if (strncmp(famstr, "PF_KEY", 6) == 0) return FALSE; if (strncmp(famstr, "PF_PACKET", 9) == 0) return FALSE; if (strncmp(famstr, "PF_LLC", 6) == 0) return FALSE; } return TRUE; } static int generate_sockets(void) { int fd, n, ret = FALSE; int cachefile; unsigned int nr_to_create = NR_SOCKET_FDS; unsigned int buffer[3]; cachefile = creat(cachefilename, S_IWUSR|S_IRUSR); if (cachefile == -1) outputerr("Couldn't open cachefile for writing! (%s)\n", strerror(errno)); else lock_cachefile(cachefile, F_WRLCK); /* * Don't loop forever if all protos all are disabled. */ if (!do_specific_proto) { for (n = 0; n < (int)ARRAY_SIZE(no_protos); n++) { if (!no_protos[n]) break; } if (n >= (int)ARRAY_SIZE(no_protos)) nr_to_create = 0; } while (nr_to_create > 0) { struct socket_triplet st; for (st.family = 0; st.family < TRINITY_PF_MAX; st.family++) { /* check for ctrl-c again. */ if (shm->exit_reason != STILL_RUNNING) goto out_unlock; if (do_specific_proto == TRUE) { st.family = specific_proto; //FIXME: If we've passed -P and we're spinning here without making progress // then we should abort after a few hundred loops. } if (get_proto_name(st.family) == NULL) continue; if (valid_proto(st.family) == FALSE) { if (do_specific_proto == TRUE) { outputerr("Can't do protocol %s\n", get_proto_name(st.family)); goto out_unlock; } else { continue; } } BUG_ON(st.family >= ARRAY_SIZE(no_protos)); if (no_protos[st.family]) continue; if (sanitise_socket_triplet(&st) == -1) rand_proto_type(&st); fd = open_socket(st.family, st.type, st.protocol); if (fd > -1) { nr_to_create--; if (cachefile != -1) { buffer[0] = st.family; buffer[1] = st.type; buffer[2] = st.protocol; n = write(cachefile, &buffer, sizeof(int) * 3); if (n == -1) { outputerr("something went wrong writing the cachefile!\n"); goto out_unlock; } } if (nr_to_create == 0) goto done; } else { //outputerr("Couldn't open family:%d (%s)\n", st.family, get_proto_name(st.family)); } } } done: ret = TRUE; output(1, "created %d sockets\n", nr_sockets); out_unlock: if (cachefile != -1) { unlock_cachefile(cachefile); close(cachefile); } return ret; } void close_sockets(void) { unsigned int i; int fd; struct linger ling = { .l_onoff = FALSE, .l_linger = 0 }; for (i = 0; i < nr_sockets; i++) { //FIXME: This is a workaround for a weird bug where we hang forevre // waiting for bluetooth sockets when we setsockopt. // Hopefully at some point we can remove this when someone figures out what's going on. if (shm->sockets[i].triplet.family == PF_BLUETOOTH) continue; /* Grab an fd, and nuke it before someone else uses it. */ fd = shm->sockets[i].fd; shm->sockets[i].fd = 0; /* disable linger */ (void) setsockopt(fd, SOL_SOCKET, SO_LINGER, &ling, sizeof(struct linger)); (void) shutdown(fd, SHUT_RDWR); if (close(fd) != 0) output(1, "failed to close socket [%d:%d:%d].(%s)\n", shm->sockets[i].triplet.family, shm->sockets[i].triplet.type, shm->sockets[i].triplet.protocol, strerror(errno)); } nr_sockets = 0; } static int open_sockets(void) { int cachefile; unsigned int domain, type, protocol; unsigned int buffer[3]; int bytesread = -1; int fd; int ret; /* If we're doing victim files we probably don't care about sockets. */ //FIXME: Is this really true ? We might want to sendfile for eg if (victim_path != NULL) return TRUE; cachefile = open(cachefilename, O_RDONLY); if (cachefile < 0) { output(1, "Couldn't find socket cachefile. Regenerating.\n"); ret = generate_sockets(); return ret; } lock_cachefile(cachefile, F_RDLCK); while (bytesread != 0) { bytesread = read(cachefile, buffer, sizeof(int) * 3); if (bytesread == 0) break; domain = buffer[0]; type = buffer[1]; protocol = buffer[2]; if ((do_specific_proto == TRUE && domain != specific_proto) || (domain < ARRAY_SIZE(no_protos) && no_protos[domain] == TRUE)) { output(1, "ignoring socket cachefile due to specific " "protocol request (or protocol disabled), " "and stale data in cachefile.\n"); regenerate: unlock_cachefile(cachefile); /* drop the reader lock. */ close(cachefile); unlink(cachefilename); close_sockets(); ret = generate_sockets(); return ret; } fd = open_socket(domain, type, protocol); if (fd < 0) { output(1, "Cachefile is stale. Need to regenerate.\n"); goto regenerate; } /* check for ctrl-c */ if (shm->exit_reason != STILL_RUNNING) { close(cachefile); return FALSE; } } if (nr_sockets < NR_SOCKET_FDS) { output(1, "Insufficient sockets in cachefile (%d). Regenerating.\n", nr_sockets); goto regenerate; } output(1, "%d sockets created based on info from socket cachefile.\n", nr_sockets); unlock_cachefile(cachefile); close(cachefile); return TRUE; }
/* fixes a socket list => resolve addresses, * interface names, fills missing members, remove duplicates */ static int fix_socket_list(struct socket_info **list) { struct socket_info* si; struct socket_info* l; struct socket_info* next; char* tmp; int len; struct hostent* he; char** h; /* try to change all the interface names into addresses * --ugly hack */ for (si=*list;si;){ next=si->next; if (add_interfaces(si->name.s, AF_INET, si->port_no, si->proto, list)!=-1){ /* success => remove current entry (shift the entire array)*/ sock_listrm(list, si); free_sock_info(si); } si=next; } /* get ips & fill the port numbers*/ #ifdef EXTRA_DEBUG LM_DBG("listening on \n"); #endif LM_DBG("fix_socket_list"); for (si=*list;si;si=si->next){ /* fix the number of processes per interface */ if (si->children==0 && (si->proto==PROTO_UDP || si->proto==PROTO_SCTP)) si->children = children_no; /* fix port number, port_no should be !=0 here */ if (si->port_no==0){ #ifdef USE_TLS si->port_no= (si->proto==PROTO_TLS)?tls_port_no:port_no; #else si->port_no= port_no; #endif } tmp=int2str(si->port_no, &len); if (len>=MAX_PORT_LEN){ LM_ERR("bad port number: %d\n", si->port_no); goto error; } si->port_no_str.s=(char*)pkg_malloc(len+1); if (si->port_no_str.s==0){ LM_ERR("out of pkg memory.\n"); goto error; } strncpy(si->port_no_str.s, tmp, len+1); si->port_no_str.len=len; LM_DBG("resolvehost [%.*s] ",si->name.len,si->name.s); /* get "official hostnames", all the aliases etc. */ he=resolvehost(si->name.s,0); if (he==0){ LM_ERR("could not resolve %s\n", si->name.s); goto error; } LM_DBG("aliases [%.*s] == [%.*s] ", (int)strlen(he->h_name),he->h_name, si->name.len, si->name.s); /* check if we got the official name */ if (strcasecmp(he->h_name, si->name.s)!=0){ if (auto_aliases && add_alias(si->name.s, si->name.len, si->port_no, si->proto)<0){ LM_ERR("add_alias failed\n"); } /* change the official name */ pkg_free(si->name.s); si->name.s=(char*)pkg_malloc(strlen(he->h_name)+1); if (si->name.s==0){ LM_ERR("out of pkg memory.\n"); goto error; } si->name.len=strlen(he->h_name); strncpy(si->name.s, he->h_name, si->name.len+1); } /* add the aliases*/ if (auto_aliases) { for(h=he->h_aliases; h && *h; h++){ LM_DBG("h_alias [%.*s] ",(int)strlen(*h),*h); if (add_alias(*h, strlen(*h), si->port_no, si->proto)<0){ LM_ERR("add_alias failed\n"); } } } hostent2ip_addr(&si->address, he, 0); /*convert to ip_addr format*/ if ((tmp=ip_addr2a(&si->address))==0) goto error; if (si->address.af == AF_INET6) { si->address_str.s=(char*)pkg_malloc(strlen(tmp)+1+2); if (si->address_str.s==0){ LM_ERR("out of pkg memory.\n"); goto error; } si->address_str.s[0] = '['; strncpy( si->address_str.s+1 , tmp, strlen(tmp)); si->address_str.s[1+strlen(tmp)] = ']'; si->address_str.s[2+strlen(tmp)] = '\0'; si->address_str.len=strlen(tmp) + 2; } else { si->address_str.s=(char*)pkg_malloc(strlen(tmp)+1); if (si->address_str.s==0){ LM_ERR("out of pkg memory.\n"); goto error; } strncpy(si->address_str.s, tmp, strlen(tmp)+1); si->address_str.len=strlen(tmp); } /* set is_ip (1 if name is an ip address, 0 otherwise) */ if ( auto_aliases && (si->address_str.len==si->name.len) && (strncasecmp(si->address_str.s, si->name.s, si->address_str.len)==0) ){ si->flags|=SI_IS_IP; /* do rev. DNS on it (for aliases)*/ he=rev_resolvehost(&si->address); if (he==0){ LM_WARN("could not rev. resolve %s\n", si->name.s); }else{ /* add the aliases*/ if (add_alias(he->h_name, strlen(he->h_name), si->port_no, si->proto)<0){ LM_ERR("add_alias failed\n"); } for(h=he->h_aliases; h && *h; h++) if (add_alias(*h,strlen(*h),si->port_no,si->proto)<0){ LM_ERR(" add_alias failed\n"); } } } /* Now build an ip_addr structure for the adv_name, if there is one * so that find_si can find it later easily. Doing this so that * we can force_send_socket() on an advertised name. Generally there * is little interest in dealing with an advertised name as anything * other than an opaque string that we blindly put into the SIP * message. */ if(si->adv_name_str.len) { /* If adv_name_str is already an IP, this is kinda foolish cus it * converts it to ip_addr, then to he, then here we go back to * ip_addr, but it's either that, or we duplicate the logic to * check for an ip address here, and still we might have to call * resolvehost(). */ he=resolvehost(si->adv_name_str.s,0); if (he==0){ LM_ERR("ERROR: fix_socket_list: could not resolve " "advertised name %s\n", si->adv_name_str.s); goto error; } hostent2ip_addr(&si->adv_address, he, 0); /*convert to ip_addr */ /* build and set string encoding for the adv socket info * This is usefful for the usrloc module when it's generating * or updating the socket on a location record, so we'll generate * it up front just like the regular sock_str so we don't have * to worry about it later. */ tmp = socket2str( si, 0, &si->adv_sock_str.len, 1); if (tmp==0) { LM_ERR("ERROR: fix_socket_list: failed to convert " "socket to string (adv)\n"); goto error; } si->adv_sock_str.s=(char*)pkg_malloc(si->adv_sock_str.len); if (si->adv_sock_str.s==0) { LM_ERR("ERROR: fix_socket_list: out of memory.\n"); goto error; } memcpy(si->adv_sock_str.s, tmp, si->adv_sock_str.len); } /* build and set string encoding for the real socket info */ tmp = socket2str( si, 0, &si->sock_str.len, 0); if (tmp==0) { LM_ERR("failed to convert socket to string"); goto error; } si->sock_str.s=(char*)pkg_malloc(si->sock_str.len); if (si->sock_str.s==0) { LM_ERR("out of pkg memory.\n"); goto error; } memcpy(si->sock_str.s, tmp, si->sock_str.len); #ifdef USE_MCAST /* Check if it is an multicast address and * set the flag if so */ if (is_mcast(&si->address)) { si->flags |= SI_IS_MCAST; } #endif /* USE_MCAST */ #ifdef EXTRA_DEBUG printf(" %.*s [%s]:%s%s\n", si->name.len, si->name.s, si->address_str.s, si->port_no_str.s, si->flags & SI_IS_MCAST ? " mcast" : ""); #endif } /* removing duplicate addresses*/ for (si=*list;si; si=si->next){ for (l=si->next;l;){ next=l->next; if ((si->port_no==l->port_no) && (si->address.af==l->address.af) && (memcmp(si->address.u.addr, l->address.u.addr, si->address.len) == 0) ){ #ifdef EXTRA_DEBUG printf("removing duplicate %s [%s] == %s [%s]\n", si->name.s, si->address_str.s, l->name.s, l->address_str.s); #endif /* add the name to the alias list*/ if ((!(l->flags& SI_IS_IP)) && ( (l->name.len!=si->name.len)|| (strncmp(l->name.s, si->name.s, si->name.len)!=0)) ) add_alias(l->name.s, l->name.len, l->port_no, l->proto); /* remove l*/ sock_listrm(list, l); free_sock_info(l); } l=next; } } #ifdef USE_MCAST /* Remove invalid multicast entries */ si=*list; while(si){ if ((si->flags & SI_IS_MCAST) && ((si->proto == PROTO_TCP) #ifdef USE_TLS || (si->proto == PROTO_TLS) #endif /* USE_TLS */ #ifdef USE_SCTP || (si->proto == PROTO_SCTP) #endif )){ LM_WARN("removing entry %s:%s [%s]:%s\n", get_proto_name(si->proto), si->name.s, si->address_str.s, si->port_no_str.s); l = si; si=si->next; sock_listrm(list, l); free_sock_info(l); } else { si=si->next; } } #endif /* USE_MCAST */ return 0; error: return -1; }