Exemple #1
0
int client_add(int fd, void (*workfn)(int ci), void (*deadfn)(int ci))
{
	int i;

	if (!client)
		client_alloc();
again:
	for (i = 0; i < client_size; i++) {
		if (client[i].fd == -1) {
			client[i].workfn = workfn;
			if (deadfn)
				client[i].deadfn = deadfn;
			else
				client[i].deadfn = client_dead;
			client[i].fd = fd;
			pollfd[i].fd = fd;
			pollfd[i].events = POLLIN;
			if (i > client_maxi)
				client_maxi = i;
			return i;
		}
	}

	client_alloc();
	goto again;
}
Exemple #2
0
static void server_on_connection(uv_stream_t *handle, int status)
{
  server_t *server = handle->data;

  // allocate client
  client_t *client = client_alloc(server->sizeof_client);

  // setup client
  client->server = server;

  // accept client
  // TODO: report errors
  uv_tcp_init(server->handle.loop, &client->handle);
  client->handle.data = client;
  // TODO: EMFILE trick!
  // https://github.com/joyent/libuv/blob/master/src/unix/ev/ev.3#L1812-1816
  if (uv_accept((uv_stream_t *)&server->handle, (uv_stream_t *)&client->handle)) {
    // accept failed? report error
    client->server->on_event(server, EVT_ERROR, uv_last_error(uv_default_loop()).code, NULL);
    exit(-2);
  }

  // fire 'open' event
  client->server->on_event(client, EVT_CLI_OPEN, 0, NULL);

  // start reading client
  uv_read_start((uv_stream_t *)&client->handle, buf_alloc, client_on_read);
}
Exemple #3
0
int
client_add(int fd, uid_t uid)
{
	int		i;

	if (client == NULL)		/* first time we're called */
		client_alloc();
again:
	for (i = 0; i < client_size; i++) {
		if (client[i].fd == -1) {	/* find an available entry */
			client[i].fd = fd;
			client[i].uid = uid;
			return(i);	/* return index in client[] array */
		}
	}
			/* client array full, time to realloc for more */
	client_alloc();
	goto again;		/* and search again (will work this time) */
}
Exemple #4
0
int client_add(int fd, uid_t uid)
{
    int     i;
    if (client == NULL)
    {
        client_alloc();
    }
again:
    for (i = 0; i < client_size; i++)
    {
        if (client[i].fd == -1)
        {
            client[i].fd = fd;
            client[i].uid = uid;
            return i;
        }
    }
    client_alloc();
    goto again;
}
Exemple #5
0
void scan_windows(void)
{
    const int screens_len = xcb_setup_roots_length(xcb_get_setup(wm_conf.connection));
    int screen_idx;
    xcb_window_t root_wins[screens_len];
    xcb_query_tree_cookie_t root_tree_cookies[screens_len];

    /* request window trees for the root window of each screen */
    for (screen_idx = 0; screen_idx < screens_len; ++screen_idx) {
        xcb_screen_t *screen = xcb_aux_get_screen(wm_conf.connection, screen_idx);
        root_wins[screen_idx] = screen->root;
        root_tree_cookies[screen_idx] = xcb_query_tree_unchecked(wm_conf.connection,
                                                                 root_wins[screen_idx]);
    }

    xcb_query_tree_reply_t *root_tree_replies[screens_len];
    xcb_window_t *wins;
    int wins_len;

    /* collect replies */
    for (screen_idx = 0; screen_idx < screens_len; ++screen_idx) {
        root_tree_replies[screen_idx] = xcb_query_tree_reply(wm_conf.connection,
                                                             root_tree_cookies[screen_idx],
                                                             NULL);
        wins = xcb_query_tree_children(root_tree_replies[screen_idx]);
        if (!wins)
            fprintf(stderr, "failed to get child tree for window %u\n", root_wins[screen_idx]);
        wins_len = xcb_query_tree_children_length(root_tree_replies[screen_idx]);
        fprintf(stderr, "root window %u has %d children\n", root_wins[screen_idx], wins_len);

        fprintf(stderr, "examining children\n");
        xcb_window_t child_win;
        int i;
        for (i = 0; i < wins_len; ++i) {
            child_win = wins[i];
            fprintf(stderr, "  child window %u\n", child_win);
            client_t *client = find_client(child_win);
            if (!client) {
                client = client_init(client_alloc());
                client->window = child_win;
                sglib_client_t_add(&client_list, client);
            }
            read_client_geometry(client);
        }
    }

    for (screen_idx = 0; screen_idx < screens_len; ++screen_idx)
        free(root_tree_replies[screen_idx]);
}
Exemple #6
0
struct srv_client*
srv_ctable_connect_direct_handler(srv_common_t *srv, srv_msg_t *m,
        seL4_CPtr liveness, int* _errno)
{
    assert(srv && srv->magic == SRV_MAGIC && m);

    /* Check that the liveness cap passed in correctly. */
    if(!srv_check_dispatch_caps(m, 0x00000000, 1)) {
        SET_ERRNO_PTR(_errno, EINVALIDPARAM);
        return NULL;
    }
    int error = ENOMEM;

    /* Copyout the liveness cap, create session cap cslot. Do not printf before the copyout. */
    seL4_CPtr livenessCP = rpc_copyout_cptr(liveness);
    if (!liveness || !livenessCP) {
        goto error0;
    }

    /* Allocate the client structure. */
    struct srv_client *c = client_alloc(&srv->clientTable, livenessCP);
    if (!c) {
        goto error1;
    }

    dprintf("Adding new %s client cID = %d. Hi! (:D)\n", srv->config.serverName, c->cID);
    assert(c->session);

    /* Authenticate the client to the process server, using its liveness cap. */
    error = proc_watch_client(c->liveness, srv->notifyClientFaultDeathAsyncEP, &c->deathID);
    if (error != ESUCCESS) {
        goto error2;
    }

    SET_ERRNO_PTR(_errno, ESUCCESS);
    return c;

    /* Exit stack. */
error2:
    client_queue_delete(&srv->clientTable, c->cID);
    client_table_postaction(&srv->clientTable);
error1:
    seL4_CNode_Delete(REFOS_CSPACE, livenessCP, REFOS_CDEPTH);
    csfree(livenessCP);
error0:
    SET_ERRNO_PTR(_errno, error);
    return NULL;

}
Exemple #7
0
client_t *manage_window(xcb_window_t window)
{
    client_t *client = client_init(client_alloc());
    client->window = window;
    sglib_client_t_add(&client_list, client);

    read_client_geometry(client);
    client->border_width = 0;
    update_client_geometry(client);
    xcb_map_window(wm_conf.connection, client->window);

    run_arrange_hook();

    return client;    
}
static void
accept_func( void*  _server, int  events )
{
    SysChannel  server  = _server;
    SysChannel  handler;
    Client      client;

    printf( "connection accepted for server channel, getting handler socket\n" );
    handler = sys_channel_create_tcp_handler( server );
    client  = client_alloc( handler );
    printf( "got one. created client %p\n", client );

    events=events;
    sys_channel_on( handler, SYS_EVENT_READ, client_handler, client );
}
Exemple #9
0
network_client *
network_client_new(uint32_t size, network_client_ops *ops,
	uint32_t factory, void *io)
{
	init_parm parm;

	if (size < sizeof(network_client))
	{
		unix_sock_close((int32_t)io);
		return NULL;
	}

	parm.opts = ops;
	parm.io = io;
	parm.factory = factory;

	return (network_client*)client_alloc(
		size, &client_ops_impl,&parm,__FUNCTION__);
}
Exemple #10
0
static void peerip_clients_close(void)
{
	struct client_t *c;
	
	c = client_alloc();
	if (!c) {
		hlog(LOG_ERR, "peerip_clients_close: client_alloc returned NULL");
		abort();
	}
	
	c->fd = -2; // Magic FD to close them all
	c->state = CSTATE_COREPEER;
	sprintf(c->filter_s, "peerip_clients_close"); // debugging
	
	if (pass_client_to_worker(worker_threads, c)) {
		hlog(LOG_ERR, "Failed to pass magic peerip_clients_close message pseudoclient to worker");
		client_free(c);
	}
}
Exemple #11
0
int client_add(int fd, const struct booth_transport *tpt,
		void (*workfn)(int ci),
		void (*deadfn)(int ci))
{
	int i;
	struct client *c;


	if (client_size - 1 <= client_maxi ) {
		client_alloc();
	}

	for (i = 0; i < client_size; i++) {
		c = clients + i;
		if (c->fd != -1)
			continue;

		c->workfn = workfn;
		if (deadfn)
			c->deadfn = deadfn;
		else
			c->deadfn = client_dead;

		c->transport = tpt;
		c->fd = fd;
		c->msg = NULL;
		c->offset = 0;

		pollfds[i].fd = fd;
		pollfds[i].events = POLLIN;
		if (i > client_maxi)
			client_maxi = i;

		return i;
	}

	assert(!"no client");
}
Exemple #12
0
void server_accept_client(struct evconnlistener *listener, evutil_socket_t sock, struct sockaddr *addr, int len, void *ptr)
{
    int port = ntohs(((struct sockaddr_in*)addr)->sin_port);
    sds ip = sdsnew(inet_ntoa(((struct sockaddr_in*)addr)->sin_addr));

    server.client_connected++;

    log_info("Accepted client socket from %s:%d, current[%d], max[%d], total[%"PRIu64"]", ip, port, server.client_current + 1, server.client_max, server.client_connected);
    if(server.client_current >= server.client_max)
    {
        ssize_t wl;
        log_warn("Reached max connection: %d, client will be closed.", server.client_current + 1);
        sds msg = sdscatprintf(sdsempty(), "%s 1%sMax connection error.", ZR_CMD_REP_ERR, ZR_MSG_NL);
        wl = write(sock, msg, sdslen(msg));
        sdsfree(msg);
        close(sock);
        return;
    }


    //struct client *c = client_alloc(sock, (struct sockaddr_in*)addr);
    client_alloc(sock, (struct sockaddr_in*)addr);
}
static REQUEST *request_setup(FILE *fp)
{	
	REQUEST *request;

	/*
	 *	Create and initialize the new request.
	 */
	request = request_alloc(NULL);

	request->packet = rad_alloc(request, 0);
	if (!request->packet) {
		ERROR("No memory");
		request_free(&request);
		return NULL;
	}

	request->reply = rad_alloc(request, 0);
	if (!request->reply) {
		ERROR("No memory");
		request_free(&request);
		return NULL;
	}

	request->listener = listen_alloc(request);
	request->client = client_alloc(request);

	request->number = 0;

	request->master_state = REQUEST_ACTIVE;
	request->child_state = REQUEST_ACTIVE;
	request->handle = NULL;
	request->server = talloc_strdup(request, "default");

	request->root = &mainconfig;

	/*
	 *	Read packet from fp
	 */
	request->packet->vps = readvp2(request->packet, fp, &filedone, "radiusd:");
	if (!request->packet->vps) {
		talloc_free(request);
		return NULL;
	}

	/*
	 *	FIXME: set IPs, etc.
	 */
	request->packet->code = PW_CODE_AUTHENTICATION_REQUEST;

	request->packet->src_ipaddr.af = AF_INET;
	request->packet->src_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_LOOPBACK);
	request->packet->src_port = 18120;

	request->packet->dst_ipaddr.af = AF_INET;
	request->packet->dst_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_LOOPBACK);
	request->packet->dst_port = 1812;

	/*
	 *	Build the reply template from the request.
	 */
	request->reply->sockfd = request->packet->sockfd;
	request->reply->dst_ipaddr = request->packet->src_ipaddr;
	request->reply->src_ipaddr = request->packet->dst_ipaddr;
	request->reply->dst_port = request->packet->src_port;
	request->reply->src_port = request->packet->dst_port;
	request->reply->id = request->packet->id;
	request->reply->code = 0; /* UNKNOWN code */
	memcpy(request->reply->vector, request->packet->vector,
	       sizeof(request->reply->vector));
	request->reply->vps = NULL;
	request->reply->data = NULL;
	request->reply->data_len = 0;

	/*
	 *	Debugging
	 */
	request->options = debug_flag;
	request->radlog = radlog_request;

	request->username = pairfind(request->packet->vps, PW_USER_NAME, 0, TAG_ANY);
	request->password = pairfind(request->packet->vps, PW_USER_PASSWORD, 0, TAG_ANY);

	return request;
}
Exemple #14
0
int make_uplink(struct uplink_config_t *l)
{
	int fd, i, addrc, arg;
	int uplink_index;
	union sockaddr_u sa; /* large enough for also IPv6 address */
	socklen_t addr_len;
	struct addrinfo *ai, *a, *ap[21];
	struct addrinfo req;
	char *addr_s = NULL;
	int port;
	struct sockaddr *srcaddr;
	socklen_t srcaddr_len;

	memset(&req, 0, sizeof(req));
	req.ai_family   = 0;
	req.ai_socktype = SOCK_STREAM;
	req.ai_protocol = IPPROTO_TCP;
	req.ai_flags    = AI_ADDRCONFIG;
	ai = NULL;
	
#ifdef USE_SSL	
	/* SSL requires both a cert and a key, or none at all */
	if ((l->certfile && !l->keyfile) || (l->keyfile && !l->certfile)) {
		hlog(LOG_ERR, "Uplink %s: Only one of sslkey and sslcert defined - both needed for SSL authentication", l->name);
		return -2;
	}
	
	/* todo: allow triggering SSL without client auth */
	if (l->keyfile && l->certfile) {
		if (!l->ssl) {
			if (config_uplink_ssl_setup(l)) {
				hlog(LOG_ERR, "Uplink '%s': SSL setup failed", l->name);
				return -2;
			}
		}
	}
#endif
	
	/* find a free uplink slot */
	for (uplink_index = 0; uplink_index < MAX_UPLINKS; uplink_index++) {
		if (!uplink_client[uplink_index])
			break;
	}
	if (uplink_index == MAX_UPLINKS) {
		hlog(LOG_ERR, "Uplink %s: No available uplink slots, %d used", l->name, MAX_UPLINKS);
		return -2;
	}
	
	if (strcasecmp(l->proto, "tcp") == 0) {
		// well, do nothing for now.
	} else if (strcasecmp(l->proto, "udp") == 0) {
		req.ai_socktype = SOCK_DGRAM;
		req.ai_protocol = IPPROTO_UDP;
#ifdef USE_SCTP
	} else if (strcasecmp(l->proto, "sctp") == 0) {
		req.ai_socktype = SOCK_STREAM;
		req.ai_protocol = IPPROTO_SCTP;
#endif
	} else {
		hlog(LOG_ERR, "Uplink %s: Unsupported protocol '%s'\n", l->name, l->proto);
		return -2;
	}
	
	port = atoi(l->port);
	if (port < 1 || port > 65535) {
		hlog(LOG_ERR, "Uplink %s: unsupported port number '%s'\n", l->name, l->port);
		return -2;
	}

	l->state = UPLINK_ST_CONNECTING;
	i = getaddrinfo(l->host, l->port, &req, &ai);
	if (i != 0) {
		hlog(LOG_INFO, "Uplink %s: address resolving failure of '%s' '%s': %s", l->name, l->host, l->port, gai_strerror(i));
		l->state = UPLINK_ST_NOT_LINKED;
		return -2;
	}

	/* Count the amount of addresses in response */
	addrc = 0;
	for (a = ai; a && addrc < 20 ; a = a->ai_next, ++addrc) {
		ap[addrc] = a; /* Up to 20 first addresses */
	}
	ap[addrc] = NULL;
	
	if (addrc == 0) {
		hlog(LOG_INFO, "Uplink %s: address resolving of '%s' '%s': returned 0 addresses", l->name, l->host, l->port);
		l->state = UPLINK_ST_NOT_LINKED;
		return -2;
	}
	
	/* Pick random address to start from */
	i = random() % addrc;
	
	/* Then lets try making socket and connection in address order */
	/* TODO: BUG: If the TCP connection succeeds, but the server rejects our
	 * login due to a bad source address (like, IPv4 would be allowed but our
	 * IPv6 address is not in the server's ACL), this currently does not switch
	 * to the next destination address.
	 * Instead it'll wait for the retry timer and then try a random
	 * destination address, and eventually succeed (unless very unlucky).
	 */
	fd = -1;
	while ((a = ap[i])) {
		ap[i] = NULL;
		addr_s = strsockaddr(a->ai_addr, a->ai_addrlen);

		hlog(LOG_INFO, "Uplink %s: Connecting to %s:%s (%s) [link %d, addr %d/%d]",
			l->name, l->host, l->port, addr_s, uplink_index, i+1, addrc);
		i++;
		if (i == addrc)
			i = 0;
		
		if ((fd = socket(a->ai_family, a->ai_socktype, a->ai_protocol)) < 0) {
			hlog(LOG_CRIT, "Uplink %s: socket(): %s\n", l->name, strerror(errno));
			hfree(addr_s);
			continue;
		}
		
		arg = 1;
		if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&arg, sizeof(arg)))
			hlog(LOG_ERR, "Uplink %s: Failed to set SO_REUSEADDR on new socket: %s", l->name, strerror(errno));
		
		/* bind source address */
		srcaddr_len = 0;
		if (a->ai_family == AF_INET && uplink_bind_v4_len != 0) {
			srcaddr = (struct sockaddr *)&uplink_bind_v4;
			srcaddr_len = uplink_bind_v4_len;
		} else if (a->ai_family == AF_INET6 && uplink_bind_v6_len != 0) {
			srcaddr = (struct sockaddr *)&uplink_bind_v6;
			srcaddr_len = uplink_bind_v6_len;
		}
		
		if (srcaddr_len) {
			if (bind(fd, srcaddr, srcaddr_len)) {
				char *s = strsockaddr(srcaddr, srcaddr_len);
				hlog(LOG_ERR, "Uplink %s: Failed to bind source address '%s': %s", l->name, s, strerror(errno));
				hfree(s);
				goto connerr;
			}
		}
		
		/* set non-blocking mode at this point, so that we can make a
		 * non-blocking connect() with a short timeout
		 */
		if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
			hlog(LOG_CRIT, "Uplink %s: Failed to set non-blocking mode on new socket: %s", l->name, strerror(errno));
			goto connerr;
		}
		
		/* Use TCP_NODELAY for APRS-IS sockets. High delays can cause packets getting past
		 * the dupe filters.
		 */
#ifdef TCP_NODELAY
		if (a->ai_protocol == IPPROTO_TCP) {
			int arg = 1;
			if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void *)&arg, sizeof(arg)))
				hlog(LOG_ERR, "Uplink %s: %s: setsockopt(TCP_NODELAY, %d) failed: %s", l->name, addr_s, arg, strerror(errno));
		}
#endif

		if (connect(fd, a->ai_addr, a->ai_addrlen) && errno != EINPROGRESS) {
			hlog(LOG_ERR, "Uplink %s: connect(%s) failed: %s", l->name, addr_s, strerror(errno));
			goto connerr;
		}
		
		/* Only wait a few seconds for the connection to be created.
		 * If the connection setup is very slow, it is unlikely to
		 * perform well enough anyway.
		 */
		struct pollfd connect_fd;
		connect_fd.fd = fd;
		connect_fd.events = POLLOUT;
		connect_fd.revents = 0;
		
		int r = poll(&connect_fd, 1, 3000);
		hlog(LOG_DEBUG, "Uplink %s: poll after connect returned %d, revents %d", l->name, r, connect_fd.revents);
		
		if (r < 0) {
			hlog(LOG_ERR, "Uplink %s: connect to %s: poll failed: %s", l->name, addr_s, strerror(errno));
			goto connerr;
		}
		
		if (r < 1) {
			hlog(LOG_ERR, "Uplink %s: connect to %s timed out", l->name, addr_s);
			goto connerr;
		}
		
		socklen_t optlen = sizeof(arg);
		if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char *)&arg, &optlen) == -1) {
			hlog(LOG_ERR, "Uplink %s: getsockopt() after connect failed: %s", l->name, strerror(errno));
			goto connerr;
		} else if (arg == 0) {
			/* Successful connect! */
			hlog(LOG_DEBUG, "Uplink %s: successful connect", l->name);
			break;
		}
		
		hlog(LOG_ERR, "Uplink %s: connect to %s failed: %s", l->name, addr_s, strerror(arg));
connerr:
		close(fd);
		fd = -1;
		hfree(addr_s);
	}

	freeaddrinfo(ai); /* Not needed anymore.. */

	if (fd < 0) {
		l->state = UPLINK_ST_NOT_LINKED;
		return -3; /* No successfull connection at any address.. */
	}

	struct client_t *c = client_alloc();
	if (!c) {
		hlog(LOG_ERR, "Uplink %s: client_alloc() failed, too many clients", l->name);
		close(fd);
		l->state = UPLINK_ST_NOT_LINKED;
		return -3; /* No successfull connection at any address.. */
	}
	
	l->client_ptr = (void *)c;
	c->uplink_index = uplink_index;
	c->fd    = fd;
	c->addr  = sa;
	c->ai_protocol = req.ai_protocol;
	c->state = CSTATE_INIT;
	/* use the default login handler */
	c->handler_line_in = &uplink_login_handler;
	c->flags    = l->client_flags;
	c->keepalive = tick;
	c->last_read = tick;
	c->connect_time = now;
	strncpy(c->username, l->name, sizeof(c->username));
	c->username[sizeof(c->username)-1] = 0;
	c->username_len = strlen(c->username);

	/* These peer/sock name calls can not fail -- or the socket closed
	   on us in which case it gets abandoned a bit further below. */

	addr_len = sizeof(sa);
	getpeername(fd, (struct sockaddr *)&sa, &addr_len);
	//s = strsockaddr( &sa.sa, addr_len ); /* server side address */
	strncpy(c->addr_rem, addr_s, sizeof(c->addr_rem));
	c->addr_rem[sizeof(c->addr_rem)-1] = 0;
	hfree(addr_s);

	/* hex format of client's IP address + port */

	char *s = hexsockaddr( &sa.sa, addr_len );
	strncpy(c->addr_hex, s, sizeof(c->addr_hex));
	c->addr_hex[sizeof(c->addr_hex)-1] = 0;
	hfree(s);

	addr_len = sizeof(sa);
	getsockname(fd, (struct sockaddr *)&sa, &addr_len);
	s = strsockaddr( &sa.sa, addr_len ); /* client side address */
	strncpy(c->addr_loc, s, sizeof(c->addr_loc));
	c->addr_loc[sizeof(c->addr_loc)-1] = 0;
	hfree(s);

	hlog(LOG_INFO, "Uplink %s: %s: Connection established on fd %d using source address %s", l->name, c->addr_rem, c->fd, c->addr_loc);
	
	if (set_client_sockopt(c) < 0)
		goto err;

	uplink_client[uplink_index] = c;
	l->state = UPLINK_ST_CONNECTED;
	
	/* set up SSL if necessary */
#ifdef USE_SSL
	if (l->ssl) {
		if (ssl_create_connection(l->ssl, c, 1))
			goto err;
	}
#endif
	
	/* Push it on the first worker, which ever it is..
	 */
	
	if (pass_client_to_worker(worker_threads, c))
		goto err;

	if ((i = pthread_mutex_lock(& uplink_connects.mutex )))
		hlog(LOG_ERR, "make_uplink: could not lock uplink_connects: %s", strerror(i));
	++ uplink_connects.gauge;
	++ uplink_connects.counter;
	++ uplink_connects.refcount;  /* <-- that does not get decremented at any time..  */
	if ((i = pthread_mutex_unlock(& uplink_connects.mutex )))
		hlog(LOG_ERR, "make_uplink: could not unlock uplink_connects: %s", strerror(i));
	
	c->portaccount = & uplink_connects; /* calculate traffic bytes/packets */
	
	return 0;
	
err:
	client_free(c);
	uplink_client[uplink_index] = NULL;
	l->state = UPLINK_ST_NOT_LINKED;
	return -1;
}
Exemple #15
0
struct client_t *accept_client_for_listener(struct listen_t *l, int fd, char *addr_s, union sockaddr_u *sa, unsigned addr_len)
{
	struct client_t *c;
	char *s;
	int i;
	union sockaddr_u sa_loc; /* local address */
	socklen_t addr_len_loc = sizeof(sa_loc);
	
	c = client_alloc();
	if (!c)
		return NULL;
		
	c->fd    = fd;
	c->listener_id = l->listener_id;
	c->addr  = *sa;
	c->ai_protocol = l->ai_protocol;
	c->portnum = l->portnum;
	c->hidden  = l->hidden;
	c->flags   = l->client_flags;
	c->udpclient = client_udp_find(udpclients, sa->sa.sa_family, l->portnum);
	c->portaccount = l->portaccount;
	c->last_read = tick; /* not simulated time */
	inbound_connects_account(1, c->portaccount); /* account all ports + port-specifics */
	
	/* text format of client's IP address + port */
	strncpy(c->addr_rem, addr_s, sizeof(c->addr_rem));
	c->addr_rem[sizeof(c->addr_rem)-1] = 0;

	/* hex format of client's IP address + port */
	s = hexsockaddr( &sa->sa, addr_len );
	strncpy(c->addr_hex, s, sizeof(c->addr_hex));
	c->addr_hex[sizeof(c->addr_hex)-1] = 0;
	hfree(s);

	/* text format of servers' connected IP address + port */
	if (getsockname(fd, &sa_loc.sa, &addr_len_loc) == 0) { /* Fails very rarely.. */
		if (addr_len_loc > sizeof(sa_loc))
			hlog(LOG_ERR, "accept_client_for_listener: getsockname for client %s truncated local address of %d to %d bytes", c->addr_rem, addr_len_loc, sizeof(sa_loc));
		/* present my socket end address as a malloced string... */
		s = strsockaddr( &sa_loc.sa, addr_len_loc );
	} else {
		s = hstrdup( l->addr_s ); /* Server's bound IP address */
		hlog(LOG_ERR, "accept_client_for_listener: getsockname for client %s failed: %s (using '%s' instead)", c->addr_rem, strerror(errno), s);
	}
	strncpy(c->addr_loc, s, sizeof(c->addr_loc));
	c->addr_loc[sizeof(c->addr_loc)-1] = 0;
	hfree(s);

	/* apply predefined filters */
	for (i = 0; i < (sizeof(l->filters)/sizeof(l->filters[0])); ++i) {
		if (l->filters[i]) {
			if (filter_parse(c, l->filters[i], 0) < 0) { /* system filters */
				hlog(LOG_ERR, "Bad system filter definition: %s", l->filters[i]);
			}
		}
	}
	if (l->filter_s) {
		strncpy(c->filter_s, l->filter_s, sizeof(c->filter_s));
		c->filter_s[FILTER_S_SIZE-1] = 0;
	}
	
	return c;
}
static REQUEST *request_setup(FILE *fp)
{
	VALUE_PAIR *vp;
	REQUEST *request;
	vp_cursor_t cursor;

	/*
	 *	Create and initialize the new request.
	 */
	request = request_alloc(NULL);

	request->packet = rad_alloc(request, false);
	if (!request->packet) {
		ERROR("No memory");
		talloc_free(request);
		return NULL;
	}

	request->reply = rad_alloc(request, false);
	if (!request->reply) {
		ERROR("No memory");
		talloc_free(request);
		return NULL;
	}

	request->listener = listen_alloc(request);
	request->client = client_alloc(request);

	request->number = 0;

	request->master_state = REQUEST_ACTIVE;
	request->child_state = REQUEST_RUNNING;
	request->handle = NULL;
	request->server = talloc_typed_strdup(request, "default");

	request->root = &main_config;

	/*
	 *	Read packet from fp
	 */
	if (readvp2(request->packet, &request->packet->vps, fp, &filedone) < 0) {
		fr_perror("unittest");
		talloc_free(request);
		return NULL;
	}

	/*
	 *	Set the defaults for IPs, etc.
	 */
	request->packet->code = PW_CODE_ACCESS_REQUEST;

	request->packet->src_ipaddr.af = AF_INET;
	request->packet->src_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_LOOPBACK);
	request->packet->src_port = 18120;

	request->packet->dst_ipaddr.af = AF_INET;
	request->packet->dst_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_LOOPBACK);
	request->packet->dst_port = 1812;

	/*
	 *	Copied from radclient
	 */
#if 1
	/*
	 *	Fix up Digest-Attributes issues
	 */
	for (vp = fr_cursor_init(&cursor, &request->packet->vps);
	     vp;
	     vp = fr_cursor_next(&cursor)) {
		/*
		 *	Double quoted strings get marked up as xlat expansions,
		 *	but we don't support that here.
		 */
		if (vp->type == VT_XLAT) {
			vp->vp_strvalue = vp->value.xlat;
			vp->value.xlat = NULL;
			vp->type = VT_DATA;
		}

		if (!vp->da->vendor) switch (vp->da->attr) {
		default:
			break;

			/*
			 *	Allow it to set the packet type in
			 *	the attributes read from the file.
			 */
		case PW_PACKET_TYPE:
			request->packet->code = vp->vp_integer;
			break;

		case PW_PACKET_DST_PORT:
			request->packet->dst_port = (vp->vp_integer & 0xffff);
			break;

		case PW_PACKET_DST_IP_ADDRESS:
			request->packet->dst_ipaddr.af = AF_INET;
			request->packet->dst_ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr;
			break;

		case PW_PACKET_DST_IPV6_ADDRESS:
			request->packet->dst_ipaddr.af = AF_INET6;
			request->packet->dst_ipaddr.ipaddr.ip6addr = vp->vp_ipv6addr;
			break;

		case PW_PACKET_SRC_PORT:
			request->packet->src_port = (vp->vp_integer & 0xffff);
			break;

		case PW_PACKET_SRC_IP_ADDRESS:
			request->packet->src_ipaddr.af = AF_INET;
			request->packet->src_ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr;
			break;

		case PW_PACKET_SRC_IPV6_ADDRESS:
			request->packet->src_ipaddr.af = AF_INET6;
			request->packet->src_ipaddr.ipaddr.ip6addr = vp->vp_ipv6addr;
			break;

		case PW_CHAP_PASSWORD: {
			int i, already_hex = 0;

			/*
			 *	If it's 17 octets, it *might* be already encoded.
			 *	Or, it might just be a 17-character password (maybe UTF-8)
			 *	Check it for non-printable characters.  The odds of ALL
			 *	of the characters being 32..255 is (1-7/8)^17, or (1/8)^17,
			 *	or 1/(2^51), which is pretty much zero.
			 */
			if (vp->length == 17) {
				for (i = 0; i < 17; i++) {
					if (vp->vp_octets[i] < 32) {
						already_hex = 1;
						break;
					}
				}
			}

			/*
			 *	Allow the user to specify ASCII or hex CHAP-Password
			 */
			if (!already_hex) {
				uint8_t *p;
				size_t len, len2;

				len = len2 = vp->length;
				if (len2 < 17) len2 = 17;

				p = talloc_zero_array(vp, uint8_t, len2);

				memcpy(p, vp->vp_strvalue, len);

				rad_chap_encode(request->packet,
						p,
						fr_rand() & 0xff, vp);
				vp->vp_octets = p;
				vp->length = 17;
			}
		}
			break;

		case PW_DIGEST_REALM:
		case PW_DIGEST_NONCE:
		case PW_DIGEST_METHOD:
		case PW_DIGEST_URI:
		case PW_DIGEST_QOP:
		case PW_DIGEST_ALGORITHM:
		case PW_DIGEST_BODY_DIGEST:
		case PW_DIGEST_CNONCE:
		case PW_DIGEST_NONCE_COUNT:
		case PW_DIGEST_USER_NAME:
			/* overlapping! */
		{
			DICT_ATTR const *da;
			uint8_t *p, *q;

			p = talloc_array(vp, uint8_t, vp->length + 2);

			memcpy(p + 2, vp->vp_octets, vp->length);
			p[0] = vp->da->attr - PW_DIGEST_REALM + 1;
			vp->length += 2;
			p[1] = vp->length;

			da = dict_attrbyvalue(PW_DIGEST_ATTRIBUTES, 0);
			rad_assert(da != NULL);
			vp->da = da;

			/*
			 *	Re-do pairmemsteal ourselves,
			 *	because we play games with
			 *	vp->da, and pairmemsteal goes
			 *	to GREAT lengths to sanitize
			 *	and fix and change and
			 *	double-check the various
			 *	fields.
			 */
			memcpy(&q, &vp->vp_octets, sizeof(q));
			talloc_free(q);

			vp->vp_octets = talloc_steal(vp, p);
			vp->type = VT_DATA;

			VERIFY_VP(vp);
		}

		break;
		}
	} /* loop over the VP's we read in */
#endif

	if (debug_flag) {
		for (vp = fr_cursor_init(&cursor, &request->packet->vps);
		     vp;
		     vp = fr_cursor_next(&cursor)) {
			/*
			 *	Take this opportunity to verify all the VALUE_PAIRs are still valid.
			 */
			if (!talloc_get_type(vp, VALUE_PAIR)) {
				ERROR("Expected VALUE_PAIR pointer got \"%s\"", talloc_get_name(vp));

				fr_log_talloc_report(vp);
				rad_assert(0);
			}

			vp_print(fr_log_fp, vp);
		}
		fflush(fr_log_fp);
	}

	/*
	 *	FIXME: set IPs, etc.
	 */
	request->packet->code = PW_CODE_ACCESS_REQUEST;

	request->packet->src_ipaddr.af = AF_INET;
	request->packet->src_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_LOOPBACK);
	request->packet->src_port = 18120;

	request->packet->dst_ipaddr.af = AF_INET;
	request->packet->dst_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_LOOPBACK);
	request->packet->dst_port = 1812;

	/*
	 *	Build the reply template from the request.
	 */
	request->reply->sockfd = request->packet->sockfd;
	request->reply->dst_ipaddr = request->packet->src_ipaddr;
	request->reply->src_ipaddr = request->packet->dst_ipaddr;
	request->reply->dst_port = request->packet->src_port;
	request->reply->src_port = request->packet->dst_port;
	request->reply->id = request->packet->id;
	request->reply->code = 0; /* UNKNOWN code */
	memcpy(request->reply->vector, request->packet->vector,
	       sizeof(request->reply->vector));
	request->reply->vps = NULL;
	request->reply->data = NULL;
	request->reply->data_len = 0;

	/*
	 *	Debugging
	 */
	request->log.lvl = debug_flag;
	request->log.func = vradlog_request;

	request->username = pairfind(request->packet->vps, PW_USER_NAME, 0, TAG_ANY);
	request->password = pairfind(request->packet->vps, PW_USER_PASSWORD, 0, TAG_ANY);

	return request;
}
Exemple #17
0
static void peerip_clients_config(void)
{
	struct client_t *c;
	struct peerip_config_t *pe;
	struct client_udp_t *udpclient;
	char *s;
	union sockaddr_u sa; /* large enough for also IPv6 address */
	socklen_t addr_len = sizeof(sa);
	
	for (pe = peerip_config; (pe); pe = pe->next) {
		hlog(LOG_DEBUG, "Setting up UDP peer %s (%s)", pe->name, pe->host);
		udpclient = client_udp_find(udppeers, pe->af, pe->local_port);
		
		if (!udpclient) {
			hlog(LOG_ERR, "Failed to find UDP socket on port %d for peer %s (%s)", pe->local_port, pe->name, pe->host);
			continue;
		}

		c = client_alloc();
		if (!c) {
			hlog(LOG_ERR, "peerip_clients_config: client_alloc returned NULL");
			abort();
		}
		c->fd = -1; // Right, this client will never have a socket of it's own.
		c->ai_protocol = IPPROTO_UDP;
		c->portnum = pe->local_port; // local port
		c->state = CSTATE_COREPEER;
		c->validated = VALIDATED_WEAK;
		c->flags = CLFLAGS_UPLINKPORT;
		c->handler_line_in = &incoming_handler;
		memcpy((void *)&c->udpaddr.sa, (void *)pe->ai->ai_addr, pe->ai->ai_addrlen);
		c->udpaddrlen = pe->ai->ai_addrlen;
		c->udp_port = pe->remote_port; // remote port
		c->addr = c->udpaddr;
		c->udpclient = udpclient;
		//c->portaccount = l->portaccount;
		c->keepalive = tick + keepalive_interval;
		c->last_read = tick; /* not simulated time */
		
		inbound_connects_account(3, c->udpclient->portaccount); /* "3" = udp, not listening..  */
		
		/* set up peer serverid to username */
		strncpy(c->username, pe->serverid, sizeof(c->username));
		c->username[sizeof(c->username)-1] = 0;
		c->username_len = strlen(c->username);
		
		/* convert client address to string */
		s = strsockaddr( &c->udpaddr.sa, c->udpaddrlen );
		
		/* text format of client's IP address + port */
		strncpy(c->addr_rem, s, sizeof(c->addr_rem));
		c->addr_rem[sizeof(c->addr_rem)-1] = 0;
		hfree(s);
		
		/* hex format of client's IP address + port */
		s = hexsockaddr( &c->udpaddr.sa, c->udpaddrlen );
		
		strncpy(c->addr_hex, s, sizeof(c->addr_hex));
		c->addr_hex[sizeof(c->addr_hex)-1] = 0;
		hfree(s);

		/* text format of servers' connected IP address + port */
		addr_len = sizeof(sa);
		if (getsockname(c->udpclient->fd, &sa.sa, &addr_len) == 0) { /* Fails very rarely.. */
			/* present my socket end address as a malloced string... */
			s = strsockaddr( &sa.sa, addr_len );
		} else {
			hlog(LOG_ERR, "Peer config: getsockname on udpclient->fd failed: %s", strerror(errno));
			s = hstrdup( "um" ); /* Server's bound IP address.. TODO: what? */
		}
		strncpy(c->addr_loc, s, sizeof(c->addr_loc));
		c->addr_loc[sizeof(c->addr_loc)-1] = 0;
		hfree(s);

		/* pass the client to the first worker thread */
		if (pass_client_to_worker(worker_threads, c)) {
			hlog(LOG_ERR, "Failed to pass UDP peer %s (%s) to worker", pe->name, pe->host);
			client_free(c);
		}
	}
}