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; }
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; }