Example #1
0
/* 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);
		}
}
Example #2
0
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);
}
Example #3
0
/* 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);
	}
}
Example #4
0
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);
}
Example #5
0
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;
}
Example #6
0
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)));
}
Example #7
0
//-----------------------------------------------
// 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;
  }

}
Example #8
0
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;
}
Example #9
0
/*!
 * \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;
}
Example #10
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);
}
Example #11
0
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;
}
Example #12
0
/* 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;
}
Example #13
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_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;
}
Example #14
0
/* 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;
}