/* * 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; }
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)); } }
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; }
static int send_udp(int fd, Msg *msg) { Octstr *cliaddr; int ret; cliaddr = udp_create_address(msg->wdp_datagram.destination_address, msg->wdp_datagram.destination_port); ret = udp_sendto(fd, msg->wdp_datagram.user_data, cliaddr); if (ret == -1) error(0, "WDP/UDP: could not send UDP datagram"); octstr_destroy(cliaddr); return ret; }
/* * 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; }
int main(int argc, char **argv) { int opt; Octstr *address; int udpsock; gwlib_init(); /* Set defaults that can't be set statically */ hostname = octstr_create("localhost"); while ((opt = getopt(argc, argv, "hg:p:i:m:")) != EOF) { switch(opt) { case 'g': octstr_destroy(hostname); hostname = octstr_create(optarg); break; case 'p': port = atoi(optarg); break; case 'i': interval = atof(optarg); break; case 'm': maxsize = atol(optarg); if (maxsize > UDP_MAXIMUM) { maxsize = UDP_MAXIMUM; warning(0, "-m: truncated to UDP maximum of" "%ld bytes.", maxsize); } break; case 'h': help(); exit(0); break; case '?': default: error(0, "Unknown option '%c'", opt); help(); exit(1); break; } } address = udp_create_address(hostname, port); udpsock = udp_client_socket(); if (udpsock < 0) exit(1); for ( ; optind < argc; optind++) { send_file(udpsock, argv[optind], address); if (interval > 0 && optind + 1 < argc) gwthread_sleep(interval); } octstr_destroy(address); octstr_destroy(hostname); gwlib_shutdown(); return 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); }
static void start_push(Octstr *rcpt_to, int isphonenum, MmsEnvelope *e, MmsMsg *msg) { List *pheaders; static unsigned char ct; /* Transaction counter -- do we need it? */ Octstr *to = NULL; Octstr *pduhdr = octstr_create(""); Octstr *s = NULL; info(0, "mms2mobile.startpush: notification to %s\n", octstr_get_cstr(rcpt_to)); if (!rcpt_to) { error(0, "mobilesender: Queue entry %s has no recipient address!", e->xqfname); goto done; } else to = octstr_duplicate(rcpt_to); ct++; octstr_append_char(pduhdr, ct); /* Pushd id */ octstr_append_char(pduhdr, 0x06); /* PUSH */ #if 1 octstr_append_char(pduhdr, 1 + 1 + 1); octstr_append_char(pduhdr, 0xbe); /* content type. */ #else octstr_append_char(pduhdr, 1 + 1 + sizeof "application/vnd.wap.mms-message"); /*header length. */ octstr_append_cstr(pduhdr, "application/vnd.wap.mms-message"); octstr_append_char(pduhdr, 0x0); /* string terminator. */ #endif octstr_append_char(pduhdr, 0xaf); /* push application ID header and value follows. */ octstr_append_char(pduhdr, 0x84); /* ... */ s = mms_tobinary(msg); if (isphonenum) { Octstr *url; octstr_url_encode(to); octstr_url_encode(s); #if 0 octstr_dump(pduhdr, 0); #endif octstr_url_encode(pduhdr); url = octstr_format("%S&text=%S%S&to=%S&udh=%%06%%05%%04%%0B%%84%%23%%F0", settings->sendsms_url, pduhdr, s, to); pheaders = http_create_empty_headers(); http_header_add(pheaders, "Connection", "close"); http_header_add(pheaders, "User-Agent", MM_NAME "/" MMSC_VERSION); http_start_request(httpcaller, HTTP_METHOD_GET, url, pheaders, NULL, 0, e, NULL); http_destroy_headers(pheaders); octstr_destroy(url); } else { /* An IP Address: Send packet, forget. */ Octstr *addr = udp_create_address(to, WAPPUSH_PORT); int sock = udp_client_socket(); if (sock > 0) { MmsEnvelopeTo *xto = gwlist_get(e->to,0); octstr_append(pduhdr, s); #if 0 octstr_dump(pduhdr, 0); #endif udp_sendto(sock, pduhdr, addr); close(sock); /* ?? */ mms_log2("Notify", octstr_imm("system"), to, -1, e ? e->msgId : NULL, NULL, NULL, "MM1", NULL,NULL); e = update_env_success(e, xto); } else { e = update_env_failed(e); error(0, "push to %s:%d failed: %s", octstr_get_cstr(to), WAPPUSH_PORT, strerror(errno)); } octstr_destroy(addr); if (e) settings->qfs->mms_queue_free_env(e); } done: octstr_destroy(to); octstr_destroy(pduhdr); octstr_destroy(s); }
static void do_mm1_push(Octstr *rcpt_to, int isphonenum, MmsEnvelope *e, MmsMsg *msg) { List *pheaders; static unsigned char ct; /* Transaction counter -- do we need it? */ Octstr *to = NULL; Octstr *pduhdr = octstr_create(""); Octstr *s = NULL; if (!rcpt_to) { mms_error(0, "MM1", NULL, "mobilesender: Queue entry %s has no recipient address!", e->xqfname); goto done; } else to = octstr_duplicate(rcpt_to); ct++; octstr_append_char(pduhdr, ct); /* Pushd id */ octstr_append_char(pduhdr, 0x06); /* PUSH */ #if 1 octstr_append_char(pduhdr, 1 + 1 + 1); octstr_append_char(pduhdr, 0xbe); /* content type. */ #else octstr_append_char(pduhdr, 1 + 1 + strlen("application/vnd.wap.mms-message") + 1); /*header length. */ octstr_append_cstr(pduhdr, "application/vnd.wap.mms-message"); octstr_append_char(pduhdr, 0x0); /* string terminator. */ #endif octstr_append_char(pduhdr, 0xaf); /* push application ID header and value follows. */ octstr_append_char(pduhdr, 0x84); /* ... */ s = mms_tobinary(msg); if (isphonenum) { Octstr *url = octstr_format("%S&text=%E%E&to=%E&udh=%%06%%05%%04%%0B%%84%%23%%F0", settings->sendsms_url, pduhdr, s, to); int status; List *rph = NULL; Octstr *rbody = NULL; MmsEnvelopeTo *xto = gwlist_get(e->to, 0); pheaders = http_create_empty_headers(); http_header_add(pheaders, "Connection", "close"); http_header_add(pheaders, "User-Agent", MM_NAME "/" MMSC_VERSION); if ((status = mms_url_fetch_content(HTTP_METHOD_GET, url, pheaders, NULL, &rph, &rbody)) < 0 || http_status_class(status) != HTTP_STATUS_SUCCESSFUL) { mms_error(0, "MM1", NULL, " Push[%s] from %s, to %s, failed, HTTP code => %d", e->xqfname, octstr_get_cstr(e->from), octstr_get_cstr(to), status); e = update_env(e,xto,0); } else { /* Successful push. */ mms_log2("Notify", octstr_imm("system"), to, -1, e ? e->msgId : NULL, NULL, NULL, "MM1", NULL,NULL); e = update_env(e, xto, 1); } http_destroy_headers(pheaders); http_destroy_headers(rph); octstr_destroy(rbody); octstr_destroy(url); } else { /* An IP Address: Send packet, forget. */ Octstr *addr = udp_create_address(to, WAPPUSH_PORT); int sock = udp_client_socket(); MmsEnvelopeTo *xto = gwlist_get(e->to,0); if (sock > 0) { octstr_append(pduhdr, s); #if 0 octstr_dump(pduhdr, 0); #endif udp_sendto(sock, pduhdr, addr); close(sock); /* ?? */ mms_log2("Notify", octstr_imm("system"), to, -1, e ? e->msgId : NULL, NULL, NULL, "MM1", NULL,NULL); e = update_env(e, xto, 1); } else { e = update_env(e, xto, 0); mms_error(0, "MM1", NULL, "push to %s:%d failed: %s", octstr_get_cstr(to), WAPPUSH_PORT, strerror(errno)); } octstr_destroy(addr); } done: octstr_destroy(to); octstr_destroy(pduhdr); octstr_destroy(s); if (e) settings->qfs->mms_queue_free_env(e); }