/* SCCP / SCTP+SUA interface */ #include #include #include #include #include #include #include #include #include #include #include #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, &tte->remote_addr, &addr_len); if (rc < 0) return rc; msgb_put(msg, rc); return tcap_tco_n_unitdata_ind(tte, msg); } 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; }