예제 #1
0
static int hsl_bts_connect(struct ipa_client_conn *link)
{
    struct msgb *msg;
    uint8_t *serno;
    char serno_buf[16];
    struct hsl_unit *unit = link->line->ops->cfg.ipa.dev;
    struct e1inp_sign_link *sign_link;

    /* send the minimal message to identify this BTS. */
    msg = ipa_msg_alloc(0);
    if (!msg)
        return -ENOMEM;

    *msgb_put(msg, 1) = 0x80;
    *msgb_put(msg, 1) = 0x80;
    *msgb_put(msg, 1) = unit->swversion;
    snprintf(serno_buf, sizeof(serno_buf), "%"PRIx64, unit->serno);
    serno = msgb_put(msg, strlen(serno_buf)+1);
    memcpy(serno, serno_buf, strlen(serno_buf));
    ipa_msg_push_header(msg, 0);
    send(link->ofd->fd, msg->data, msg->len, 0);
    msgb_free(msg);

    /* ... and enable the signalling link. */
    if (!link->line->ops->sign_link_up) {
        LOGP(DLINP, LOGL_ERROR,
             "Unable to set signal link, closing socket.\n");
        ipa_client_conn_close(link);
        return -EINVAL;
    }
    sign_link = link->line->ops->sign_link_up(&unit,
                link->line, E1INP_SIGN_NONE);
    if (sign_link == NULL) {
        LOGP(DLINP, LOGL_ERROR,
             "Unable to set signal link, closing socket.\n");
        ipa_client_conn_close(link);
        return -EINVAL;
    }
    return 0;
}
예제 #2
0
int ipa_msg_recv_buffered(int fd, struct msgb **rmsg, struct msgb **tmp_msg)
{
	struct msgb *msg = tmp_msg ? *tmp_msg : NULL;
	struct ipaccess_head *hh;
	int len, ret;
	int needed;

	if (msg == NULL) {
		msg = ipa_msg_alloc(0);
		if (msg == NULL) {
			ret = -ENOMEM;
			goto discard_msg;
		}
		msg->l1h = msg->tail;
	}

	if (msg->l2h == NULL) {
		/* first read our 3-byte header */
		needed = sizeof(*hh) - msg->len;
		ret = recv(fd, msg->tail, needed, 0);
		if (ret == 0)
		       goto discard_msg;

		if (ret < 0) {
			if (errno == EAGAIN || errno == EINTR)
				ret = 0;
			else {
				ret = -errno;
				goto discard_msg;
			}
		}

		msgb_put(msg, ret);

		if (ret < needed) {
			if (msg->len == 0) {
				ret = -EAGAIN;
				goto discard_msg;
			}

			LOGP(DLINP, LOGL_INFO,
			     "Received part of IPA message header (%d/%zu)\n",
			     msg->len, sizeof(*hh));
			if (!tmp_msg) {
				ret = -EIO;
				goto discard_msg;
			}
			*tmp_msg = msg;
			return -EAGAIN;
		}

		msg->l2h = msg->tail;
	}

	hh = (struct ipaccess_head *) msg->data;

	/* then read the length as specified in header */
	len = ntohs(hh->len);

	if (len < 0 || IPA_ALLOC_SIZE < len + sizeof(*hh)) {
		LOGP(DLINP, LOGL_ERROR, "bad message length of %d bytes, "
					"received %d bytes\n", len, msg->len);
		ret = -EIO;
		goto discard_msg;
	}

	needed = len - msgb_l2len(msg);

	if (needed > 0) {
		ret = recv(fd, msg->tail, needed, 0);

		if (ret == 0)
			goto discard_msg;

		if (ret < 0) {
			if (errno == EAGAIN || errno == EINTR)
				ret = 0;
			else {
				ret = -errno;
				goto discard_msg;
			}
		}

		msgb_put(msg, ret);

		if (ret < needed) {
			LOGP(DLINP, LOGL_INFO,
			     "Received part of IPA message L2 data (%d/%d)\n",
			    msgb_l2len(msg), len);
			if (!tmp_msg) {
				ret = -EIO;
				goto discard_msg;
			}
			*tmp_msg = msg;
			return -EAGAIN;
		}
	}

	ret = msgb_l2len(msg);

	if (ret == 0) {
		LOGP(DLINP, LOGL_INFO,
		     "Discarding IPA message without payload\n");
		ret = -EAGAIN;
		goto discard_msg;
	}

	if (tmp_msg)
		*tmp_msg = NULL;
	*rmsg = msg;
	return ret;

discard_msg:
	if (tmp_msg)
		*tmp_msg = NULL;
	msgb_free(msg);
	return ret;
}