+/* Callback from select layer if we can read from the sink socket */
+static int gsmtap_sink_fd_cb(struct bsc_fd *fd, unsigned int flags)
+{
+ int rc;
+ uint8_t buf[4096];
+
+ if (!(flags & BSC_FD_READ))
+ return 0;
+
+ rc = read(fd->fd, buf, sizeof(buf));
+ if (rc < 0) {
+ perror("reading from gsmtap sink fd");
+ return rc;
+ }
+ /* simply discard any data arriving on the socket */
+
+ return 0;
+}
+
+/* Create a local 'gsmtap sink' avoiding the UDP packets being rejected
+ * with ICMP reject messages */
+int gsmtap_sink_init(uint32_t bind_ip)
+{
+ int rc;
+ struct sockaddr_in sin;
+
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(GSMTAP_UDP_PORT);
+ sin.sin_addr.s_addr = htonl(bind_ip);
+
+ rc = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (rc < 0) {
+ perror("creating UDP socket");
+ return rc;
+ }
+ gsmtap_sink_bfd.fd = rc;
+ rc = bind(rc, (struct sockaddr *)&sin, sizeof(sin));
+ if (rc < 0) {
+ perror("binding UDP socket");
+ close(gsmtap_sink_bfd.fd);
+ gsmtap_sink_bfd.fd = -1;
+ return rc;
+ }
+
+ gsmtap_sink_bfd.when = BSC_FD_READ;
+ gsmtap_sink_bfd.cb = gsmtap_sink_fd_cb;
+ gsmtap_sink_bfd.data = NULL;
+
+ return bsc_register_fd(&gsmtap_sink_bfd);
+
+}
+