Example #1
0
Usage: test_udp client server_port\n\
       test_udp server server_port\n\
";

#define PING "ping"
#define PONG "pong"
#define TIMES 10

static void client(int port) {
    int i, s;
    Octstr *ping, *pong, *addr, *from;

    s = udp_client_socket();
    ping = octstr_create(PING);
    addr = udp_create_address(octstr_create("localhost"), port);
    if (s == -1 || addr == NULL)
        panic(0, "Couldn't set up client socket.");

    for (i = 0; i < TIMES; ++i) {
        if (udp_sendto(s, ping, addr) == -1)
            panic(0, "Couldn't send ping.");
        if (udp_recvfrom(s, &pong, &from) == -1)
            panic(0, "Couldn't receive pong");
        info(0, "Got <%s> from <%s:%d>", octstr_get_cstr(pong),
             octstr_get_cstr(udp_get_ip(from)),
             udp_get_port(from));
    }
}
Example #2
0
static Udpc *udpc_create(int port, char *interface_name)
{
    Udpc *udpc;
    Octstr *os;
    int fl;
    
    udpc = gw_malloc(sizeof(Udpc));
    udpc->fd = udp_bind(port, interface_name);

    os = octstr_create(interface_name);
    udpc->addr = udp_create_address(os, port);
    octstr_destroy(os);
    if (udpc->addr == NULL) {
	error(0, "updc_create: could not resolve interface <%s>",
	      interface_name);
	close(udpc->fd);
	gw_free(udpc);
	return NULL;
    }

    fl = fcntl(udpc->fd, F_GETFL);
    fcntl(udpc->fd, F_SETFL, fl | O_NONBLOCK);

    os = udp_get_ip(udpc->addr);
    debug("bb.udp", 0, "udpc_create: Bound to UDP <%s:%d>",
	  octstr_get_cstr(os), udp_get_port(udpc->addr));

    octstr_destroy(os);
    
    udpc->outgoing_list = gwlist_create();

    return udpc;
}    
Example #3
0
static int udp_set_sport(struct sock *sk, unsigned short nport)
{
	int hash, err = -1;

	udp_htable_lock();
	/*
	 * Order cannot be reversed:
	 *  1. check used port
	 *  2. select a number automatically and check it
	 */
	if ((nport && port_used(_ntohs(nport))) ||
		(!nport && !(nport = udp_get_port())))
		goto unlock;

	err = 0;
	/* update best slot */
	hash = _ntohs(nport) & UDP_HASH_MASK;
	udp_update_best(hash);

	/* add sock int udp hash table */
	sk->hash = hash;
	sk->sk_sport = nport;
	if (sk->ops->hash)
		sk->ops->hash(sk);
unlock:
	udp_htable_unlock();
	return err;
}
Example #4
0
/*
 * this function receives an WDP message and adds it to
 * corresponding outgoing_list.
 */
static int udp_addwdp_from_server(Msg *msg)
{
    Udpc *udpc;
    Octstr *os;
    Octstr *source;

    if (!udp_running) return -1;
    assert(msg != NULL);
    assert(msg_type(msg) == wdp_datagram);

    octstr_destroy(msg->wdp_datagram.source_address);
    msg->wdp_datagram.source_address = 
        octstr_create(octstr_get_cstr(msg->wdp_datagram.destination_address));
    msg->wdp_datagram.source_port = msg->wdp_datagram.destination_port;

    if ((udpc = udpc_find_mapping(msg, 0)) == NULL) 
        /* there should have been one */
        panic(0,"Could not find UDP mapping, internal error");

    /* insert the found mapped destination */
    octstr_destroy(msg->wdp_datagram.source_address);
    octstr_destroy(msg->wdp_datagram.destination_address);
    
    msg->wdp_datagram.destination_address = udp_get_ip(udpc->map_addr);
    msg->wdp_datagram.destination_port = udp_get_port(udpc->map_addr);

    /* now search for our inbound UDP socket */
    os = octstr_duplicate(interface_name);
    source = udp_create_address(os, server_port);

    msg->wdp_datagram.source_address = udp_get_ip(source);
    msg->wdp_datagram.source_port = udp_get_port(source);
    if ((udpc = udpc_find_mapping(msg, 0)) == NULL) 
        panic(0,"Could not find main inbound UDP socket, internal error");

    /* 
     * ok, got the destination, got the socket, 
     * now put it on the outbound queue
     */
    gwlist_produce(udpc->outgoing_list, msg);

    octstr_destroy(os);

    return 0;
}
Example #5
0
/*
 * this function receives an WDP message and checks if a UDP
 * service for this client has to be created
 */
static int udp_addwdp_from_client(Msg *msg)
{
    Udpc *udpc;
    Octstr *map_addr;
    Octstr *os;
    Octstr *source;
    
    if (!udp_running) return -1;
    assert(msg != NULL);
    assert(msg_type(msg) == wdp_datagram);
    
    /* 
     * Check if there is allready a bound UDP port for this mapping.
     * If not create a mapping and bind the mapped UDP port
     * The mapped port is simply 2x of the client port. 
     */
    if ((udpc = udpc_find_mapping(msg, 1)) == NULL) {
        info(0, "Creating UDP mapping <%s:%ld> <-> <%s:%ld>",
              octstr_get_cstr(msg->wdp_datagram.source_address),
              msg->wdp_datagram.source_port,
              octstr_get_cstr(msg->wdp_datagram.destination_address),
              msg->wdp_datagram.source_port*2);

        map_addr = udp_create_address(msg->wdp_datagram.source_address, 
                                      msg->wdp_datagram.source_port);
        add_service(msg->wdp_datagram.source_port * 2, 
                    octstr_get_cstr(interface_name), map_addr);
        /* now we should find it in the udpc_list */
        if ((udpc = udpc_find_mapping(msg, 1)) == NULL)
            panic(0,"Could not find UDP mapping, internal error");
    }

    /* now swap the message addressing */
    octstr_destroy(msg->wdp_datagram.source_address);
    octstr_destroy(msg->wdp_datagram.destination_address);

    os = octstr_duplicate(interface_name);
    source = udp_create_address(os, msg->wdp_datagram.source_port * 2);
    msg->wdp_datagram.source_address = udp_get_ip(source);
    msg->wdp_datagram.source_port = udp_get_port(source);
    msg->wdp_datagram.destination_address = octstr_duplicate(wapgw);
    msg->wdp_datagram.destination_port = CONNECTION_ORIENTED_PORT;

    octstr_destroy(os);

    gwlist_produce(udpc->outgoing_list, msg);
    
    return -1;
}
Example #6
0
static void server(int port) {
    int i, s;
    Octstr *ping, *pong, *from;

    s = udp_bind(port,"0.0.0.0");
    pong = octstr_create(PONG);
    if (s == -1)
        panic(0, "Couldn't set up client socket.");

    for (i = 0; i < TIMES; ++i) {
        if (udp_recvfrom(s, &ping, &from) == -1)
            panic(0, "Couldn't receive ping");
        info(0, "Got <%s> from <%s:%d>", octstr_get_cstr(ping),
             octstr_get_cstr(udp_get_ip(from)),
             udp_get_port(from));
        if (udp_sendto(s, pong, from) == -1)
            panic(0, "Couldn't send pong.");
    }
}
Example #7
0
/*
 * this function receives an WDP message and adds it to
 * corresponding outgoing_list.
 */
int udp_addwdp(Msg *msg)
{
    int i;
    Udpc *udpc, *def_udpc;
    Octstr *ip;
    
    def_udpc = NULL;
    if (!udp_running) return -1;
    assert(msg != NULL);
    assert(msg_type(msg) == wdp_datagram);
    
    gwlist_lock(udpc_list);
    /* select in which list to add this */
    for (i=0; i < gwlist_len(udpc_list); i++) {
		udpc = gwlist_get(udpc_list, i);

		if (msg->wdp_datagram.source_port == udp_get_port(udpc->addr)) {
                    def_udpc = udpc;
                    ip = udp_get_ip(udpc->addr);
		    if (octstr_compare(msg->wdp_datagram.source_address, ip) == 0) {
                        octstr_destroy(ip);
	    		gwlist_produce(udpc->outgoing_list, msg);
	    		gwlist_unlock(udpc_list);
	    		return 0;
		    }
                    octstr_destroy(ip);
		}
    }

    if (NULL != def_udpc) {
	gwlist_produce(def_udpc->outgoing_list, msg);
	gwlist_unlock(udpc_list);
	return 0;
    }

    gwlist_unlock(udpc_list);
    return -1;
}
Example #8
0
static Udpc *udpc_find_mapping(Msg *msg, int inbound)
{
    int i;
    Udpc *udpc;
    Octstr *addr;
    
    /* check if there is allready a bound UDP port */
    gwlist_lock(udpc_list);
    for (i=0; i < gwlist_len(udpc_list); i++) {
        udpc = gwlist_get(udpc_list, i);

        /* decide if we compare against inbound or outbound traffic mapping */
        addr = inbound ? udpc->map_addr : udpc->addr;

        if (msg->wdp_datagram.source_port == udp_get_port(addr) &&
            octstr_compare(msg->wdp_datagram.source_address, 
                           udp_get_ip(addr)) == 0) {
            gwlist_unlock(udpc_list);
            return udpc;
        }
    }
    gwlist_unlock(udpc_list);
    return NULL;
}
Example #9
0
static void udp_receiver(void *arg)
{
    Octstr *datagram, *cliaddr;
    int ret;
    Msg *msg;
    Udpc *conn = arg;
    Octstr *ip;

    gwlist_add_producer(incoming_wdp);
    gwlist_add_producer(flow_threads);
    gwthread_wakeup(MAIN_THREAD_ID);
    
    /* remove messages from socket until it is closed */
    while (bb_status != BB_DEAD && bb_status != BB_SHUTDOWN) {

	gwlist_consume(isolated);	/* block here if suspended/isolated */

	if (read_available(conn->fd, 100000) < 1)
	    continue;

	ret = udp_recvfrom(conn->fd, &datagram, &cliaddr);
	if (ret == -1) {
	    if (errno == EAGAIN)
		/* No datagram available, don't block. */
		continue;

	    error(errno, "Failed to receive an UDP");
	    /*
	     * just continue, or is there ANY error that would result
	     * in situation where it would be better to break; or even
	     * die off?     - Kalle 28.2
	     */
	    continue;
	}

	/* discard the message if the client is not allowed */
    	ip = udp_get_ip(cliaddr);
	if (!is_allowed_ip(allow_ip, deny_ip, ip)) {
    	    warning(0, "UDP: Discarding packet from %s, IP is denied.",
		       octstr_get_cstr(ip));
    	    octstr_destroy(datagram);
	} else {
	    debug("bb.udp", 0, "datagram received");
	    msg = msg_create(wdp_datagram);
    
	    msg->wdp_datagram.source_address = udp_get_ip(cliaddr);
	    msg->wdp_datagram.source_port    = udp_get_port(cliaddr);
	    msg->wdp_datagram.destination_address = udp_get_ip(conn->addr);
	    msg->wdp_datagram.destination_port    = udp_get_port(conn->addr);
	    msg->wdp_datagram.user_data = datagram;
    
	    gwlist_produce(incoming_wdp, msg);
	    counter_increase(incoming_wdp_counter);
	}

	octstr_destroy(cliaddr);
	octstr_destroy(ip);
    }    
    gwlist_remove_producer(incoming_wdp);
    gwlist_remove_producer(flow_threads);
}
Example #10
0
static void proxy_thread(void *arg)
{
    int ss, cs; /* server and client sockets */
    int fl; /* socket flags */
    Octstr *addr = NULL;
    int forward;
    Octstr *tmp;

    run_thread = 1;
    ss = cs = -1;

    /* create client binding, only if we have a remote server
     * and make the client socet non-blocking */
    if (remote_host != NULL) {
        cs = udp_client_socket();
        fl = fcntl(cs, F_GETFL);
        fcntl(cs, F_SETFL, fl | O_NONBLOCK);
        addr = udp_create_address(remote_host, remote_port);
    }

    /* create server binding */
    ss = udp_bind(our_port, octstr_get_cstr(our_host));

    /* make the server socket non-blocking */
    fl = fcntl(ss, F_GETFL);
    fcntl(ss, F_SETFL, fl | O_NONBLOCK);

    if (ss == -1)
        panic(0, "RADIUS: Couldn't set up server socket for port %ld.", our_port);

    while (run_thread) {
        RADIUS_PDU *pdu, *r;
        Octstr *data, *rdata;
        Octstr *from_nas, *from_radius;

        pdu = r = NULL;
        data = rdata = from_nas = from_radius = NULL;
        
        if (read_available(ss, 100000) < 1)
            continue;

        /* get request from NAS */
        if (udp_recvfrom(ss, &data, &from_nas) == -1) {
            if (errno == EAGAIN)
                /* No datagram available, don't block. */
                continue;

            error(0, "RADIUS: Couldn't receive request data from NAS");
            continue;
        }

        tmp = udp_get_ip(from_nas);
        info(0, "RADIUS: Got data from NAS <%s:%d>",
             octstr_get_cstr(tmp), udp_get_port(from_nas));
        octstr_destroy(tmp);
        octstr_dump(data, 0);

        /* unpacking the RADIUS PDU */
        if ((pdu = radius_pdu_unpack(data)) == NULL) {
            warning(0, "RADIUS: Couldn't unpack PDU from NAS, ignoring.");
            goto error;
        }
        info(0, "RADIUS: from NAS: PDU type: %s", pdu->type_name);

        /* authenticate the Accounting-Request packet */
        if (radius_authenticate_pdu(pdu, &data, secret_nas) == 0) {
            warning(0, "RADIUS: Authentication failed for PDU from NAS, ignoring.");
            goto error;
        }

        /* store to hash table if not present yet */
        mutex_lock(radius_mutex);
        forward = update_tables(pdu);
        mutex_unlock(radius_mutex);

        /* create response PDU for NAS */
        r = radius_pdu_create(0x05, pdu);

        /*
         * create response authenticator 
         * code+identifier(req)+length+authenticator(req)+(attributes)+secret 
         */
        r->u.Accounting_Response.identifier = pdu->u.Accounting_Request.identifier;
        r->u.Accounting_Response.authenticator =
            octstr_duplicate(pdu->u.Accounting_Request.authenticator);

        /* pack response for NAS */
        rdata = radius_pdu_pack(r);

        /* creates response autenticator in encoded PDU */
        radius_authenticate_pdu(r, &rdata, secret_nas);

        /* 
         * forward request to remote RADIUS server only if updated
         * and if we have a configured remote RADIUS server 
         */
        if ((remote_host != NULL) && forward) {
            if (udp_sendto(cs, data, addr) == -1) {
                error(0, "RADIUS: Couldn't send to remote RADIUS <%s:%ld>.",
                      octstr_get_cstr(remote_host), remote_port);
            } else 
            if (read_available(cs, remote_timeout) < 1) {
                error(0, "RADIUS: Timeout for response from remote RADIUS <%s:%ld>.",
                      octstr_get_cstr(remote_host), remote_port);
            } else 
            if (udp_recvfrom(cs, &data, &from_radius) == -1) {
                error(0, "RADIUS: Couldn't receive from remote RADIUS <%s:%ld>.",
                      octstr_get_cstr(remote_host), remote_port);
            } else {
                info(0, "RADIUS: Got data from remote RADIUS <%s:%d>.",
                     octstr_get_cstr(udp_get_ip(from_radius)), udp_get_port(from_radius));
                octstr_dump(data, 0);

                /* XXX unpack the response PDU and check if the response
                 * authenticator is valid */
            }
        }

        /* send response to NAS */
        if (udp_sendto(ss, rdata, from_nas) == -1)
            error(0, "RADIUS: Couldn't send response data to NAS <%s:%d>.",
                  octstr_get_cstr(udp_get_ip(from_nas)), udp_get_port(from_nas));

error:
        radius_pdu_destroy(pdu);
        radius_pdu_destroy(r);

        octstr_destroy(rdata);
        octstr_destroy(data);
        octstr_destroy(from_nas);

        debug("radius.proxy", 0, "RADIUS: Mapping table contains %ld elements",
              dict_key_count(radius_table));
        debug("radius.proxy", 0, "RADIUS: Session table contains %ld elements",
              dict_key_count(session_table));
        debug("radius.proxy", 0, "RADIUS: Client table contains %ld elements",
              dict_key_count(client_table));

    }

    octstr_destroy(addr);
}
Example #11
0
static void udp_receiver(void *arg)
{
    Octstr *datagram, *cliaddr;
    int ret;
    Msg *msg;
    Udpc *conn = arg;
    Octstr *ip;

    gwlist_add_producer(incoming_wdp);
    gwlist_add_producer(flow_threads);
    gwthread_wakeup(MAIN_THREAD_ID);
    
    /* remove messages from socket until it is closed */
    while (1) {

        if (read_available(conn->fd, 100000) < 1)
            continue;

        ret = udp_recvfrom(conn->fd, &datagram, &cliaddr);
        if (ret == -1) {
            if (errno == EAGAIN)
                /* No datagram available, don't block. */
                continue;

            error(errno, "Failed to receive an UDP");
            continue;
        }

    	ip = udp_get_ip(cliaddr);
        msg = msg_create(wdp_datagram);
    
        msg->wdp_datagram.source_address = udp_get_ip(cliaddr);
        msg->wdp_datagram.source_port = udp_get_port(cliaddr);
        msg->wdp_datagram.destination_address = udp_get_ip(conn->addr);
        msg->wdp_datagram.destination_port = udp_get_port(conn->addr);
        msg->wdp_datagram.user_data = datagram;

        info(0, "datagram received <%s:%d> -> <%s:%d>",
             octstr_get_cstr(udp_get_ip(cliaddr)), udp_get_port(cliaddr),
             octstr_get_cstr(udp_get_ip(conn->addr)), udp_get_port(conn->addr));

        dump(msg);

        /* 
         * Descide if this is (a) or (b) UDP packet and add them to the
         * corresponding queues
         */
        if (octstr_compare(conn->addr, conn->map_addr) == 0) {
            gwlist_produce(incoming_wdp, msg);
            counter_increase(incoming_wdp_counter);
        } else {
            gwlist_produce(outgoing_wdp, msg);
	        counter_increase(outgoing_wdp_counter);
        }        

        octstr_destroy(cliaddr);
        octstr_destroy(ip);
    }    
    gwlist_remove_producer(incoming_wdp);
    gwlist_remove_producer(flow_threads);
}