diff --git a/include/osmocom/core/gsmtap_util.h b/include/osmocom/core/gsmtap_util.h index 33ade95c7..9137c1d25 100644 --- a/include/osmocom/core/gsmtap_util.h +++ b/include/osmocom/core/gsmtap_util.h @@ -39,11 +39,15 @@ static inline int gsmtap_inst_fd(struct gsmtap_inst *gti) } int gsmtap_source_init_fd(const char *host, uint16_t port); +int gsmtap_source_init_fd2(const char *local_host, uint16_t local_port, const char *rem_host, uint16_t rem_port); int gsmtap_source_add_sink_fd(int gsmtap_fd); struct gsmtap_inst *gsmtap_source_init(const char *host, uint16_t port, int ofd_wq_mode); +struct gsmtap_inst *gsmtap_source_init2(const char *local_host, uint16_t local_port, + const char *rem_host, uint16_t rem_port, int ofd_wq_mode); + void gsmtap_source_free(struct gsmtap_inst *gti); int gsmtap_source_add_sink(struct gsmtap_inst *gti); diff --git a/src/core/gsmtap_util.c b/src/core/gsmtap_util.c index 4dd2acf6c..57b7aed63 100644 --- a/src/core/gsmtap_util.c +++ b/src/core/gsmtap_util.c @@ -253,6 +253,30 @@ int gsmtap_source_init_fd(const char *host, uint16_t port) OSMO_SOCK_F_CONNECT); } +/*! Create a new (sending) GSMTAP source socket + * \param[in] local_host local host name or IP address in string format + * \param[in] local_port local UDP port number in host byte order + * \param[in] rem_host remote host name or IP address in string format + * \param[in] rem_port remote UDP port number in host byte order + * \return file descriptor of the new socket + * + * Opens a GSMTAP source (sending) socket, connect it to remote host/port, + * bind to local host/port and return resulting fd. + * If \a local_host is NULL, the default address is used. + * If \a local_port is 0, than random unused port will be selected by OS. + * If \a rem_host is NULL, the destination address will be localhost. + * If \a rem_port is 0, the default \ref GSMTAP_UDP_PORT will be used. + */ +int gsmtap_source_init_fd2(const char *local_host, uint16_t local_port, const char *rem_host, uint16_t rem_port) +{ + if (!local_host) + return gsmtap_source_init_fd(rem_host, rem_port); + + return osmo_sock_init2(AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, local_host, local_port, + rem_host ? rem_host : "localhost", rem_port ? rem_port : GSMTAP_UDP_PORT, + OSMO_SOCK_F_BIND | OSMO_SOCK_F_CONNECT); +} + /*! Add a local sink to an existing GSMTAP source and return fd * \param[in] gsmtap_fd file descriptor of the gsmtap socket * \returns file descriptor of locally bound receive socket @@ -452,17 +476,18 @@ int gsmtap_source_add_sink(struct gsmtap_inst *gti) * \param[in] ofd_wq_mode Register \ref osmo_wqueue (1) or not (0) * \return callee-allocated \ref gsmtap_inst * - * Open GSMTAP source (sending) socket, connect it to host/port, + * Open GSMTAP source (sending) socket, connect it to remote host/port, + * bind it local host/port, * allocate 'struct gsmtap_inst' and optionally osmo_fd/osmo_wqueue * registration. */ -struct gsmtap_inst *gsmtap_source_init(const char *host, uint16_t port, - int ofd_wq_mode) +struct gsmtap_inst *gsmtap_source_init2(const char *local_host, uint16_t local_port, + const char *rem_host, uint16_t rem_port, int ofd_wq_mode) { struct gsmtap_inst *gti; int fd, rc; - fd = gsmtap_source_init_fd(host, port); + fd = gsmtap_source_init_fd2(local_host, local_port, rem_host, rem_port); if (fd < 0) return NULL; @@ -486,6 +511,22 @@ struct gsmtap_inst *gsmtap_source_init(const char *host, uint16_t port, return gti; } +/*! Open GSMTAP source socket, connect and register osmo_fd + * \param[in] host host name or IP address in string format + * \param[in] port UDP port number in host byte order + * \param[in] ofd_wq_mode Register \ref osmo_wqueue (1) or not (0) + * \return callee-allocated \ref gsmtap_inst + * + * Open GSMTAP source (sending) socket, connect it to host/port, + * allocate 'struct gsmtap_inst' and optionally osmo_fd/osmo_wqueue + * registration. + */ +struct gsmtap_inst *gsmtap_source_init(const char *host, uint16_t port, + int ofd_wq_mode) +{ + return gsmtap_source_init2(NULL, 0, host, port, ofd_wq_mode); +} + void gsmtap_source_free(struct gsmtap_inst *gti) { if (gti->ofd_wq_mode) {