libosmo-tcap/src/scXp.c

148 lines
4.1 KiB
C

/* SCCP / SCTP+SUA interface */
/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
* (C) 2010 by On-Waves
*
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <osmocore/logging.h>
#include <osmocore/msgb.h>
#include <osmocore/talloc.h>
#include "tcap_user.h"
#include "tcap.h"
/* prototype of what we need to call in case of incoming UNITDATA */
int tcap_tco_n_unitdata_ind(struct tcap_transport_entity *se, struct msgb *msg);
/* prototype of what we need to call in case of incoming NOTICE */
int tcap_tco_n_notice_ind(struct tcap_transport_entity *se);
/***********************************************************************/
/* Simple UDP transport (not according to any kind of official spec) */
/***********************************************************************/
static int tcap_tp_udp_unitdata_req(struct tcap_transport_entity *se, struct msgb *msg)
{
return write_queue_enqueue(&se->udp.write_queue, msg);
}
/* called by the write queue / FD magic in case we need to write a message */
static int udp_write_cb(struct bsc_fd *fd, struct msgb *msg)
{
struct write_queue *wq = container_of(fd, struct write_queue, bfd);
struct tcap_transport_entity *tte = container_of(wq, struct tcap_transport_entity, udp.write_queue);
return sendto(fd->fd, msg->data, msg->len, 0, (struct sockaddr *) &tte->remote_addr, sizeof(tte->remote_addr));
}
/* called by write queue / FD magic in case the socket has some data */
static int udp_read_cb(struct bsc_fd *fd)
{
struct write_queue *wq = container_of(fd, struct write_queue, bfd);
struct tcap_transport_entity *tte = container_of(wq, struct tcap_transport_entity, udp.write_queue);
struct msgb *msg = msgb_alloc_headroom(4096+128, 128, "incoming TCAP/UDP");
socklen_t addr_len = sizeof(tte->remote_addr);
int rc;
if (!msg)
return -ENOMEM;
rc = recvfrom(fd->fd, msg->data, msgb_tailroom(msg), 0,
(struct sockaddr *) &tte->remote_addr, &addr_len);
if (rc < 0)
return rc;
msgb_put(msg, rc);
rc = tcap_tco_n_unitdata_ind(tte, msg);
msgb_free(msg);
return rc;
}
LIB_EXPORTED struct tcap_transport_entity *tcap_transp_udp_create(struct sockaddr_storage *local_addr)
{
struct tcap_transport_entity *tte = talloc_zero(NULL, struct tcap_transport_entity);
struct write_queue *wq;
int rc;
if (!tte)
return NULL;
memcpy(&tte->local_addr, local_addr, sizeof(tte->local_addr));
tte->type = SCXP_T_UDP;
/* Initialize write queue */
wq = &tte->udp.write_queue;
write_queue_init(wq, 100);
wq->read_cb = udp_read_cb;
wq->write_cb = udp_write_cb;
wq->bfd.fd = socket(tte->local_addr.ss_family, SOCK_DGRAM, IPPROTO_UDP);
if (wq->bfd.fd < 0)
goto err_free;
rc = bind(wq->bfd.fd, (struct sockaddr *) &tte->local_addr, sizeof(tte->local_addr));
if (rc < 0)
goto err_close;
wq->bfd.when |= BSC_FD_READ;
bsc_register_fd(&wq->bfd);
return tte;
err_close:
close(wq->bfd.fd);
err_free:
talloc_free(tte);
return NULL;
}
/* Called by TCAP stack if it wants to request transmission of UNITDATA */
int tcap_scXp_n_unitdata_req(struct tcap_transport_entity *se, struct msgb *msg)
{
int rc = 0;
printf("N-UNITDATA.req(%s)\n", hexdump(msg->data, msg->len));
#if 0
int i = open("ber.out", O_CREAT|O_WRONLY|O_TRUNC);
write(i, msg->data, msg->len);
close(i);
#endif
switch (se->type) {
case SCXP_T_UDP:
rc = write_queue_enqueue(&se->udp.write_queue, msg);
break;
}
return rc;
}