📄 isns.c
字号:
length += isns_tlv_set(&tlv, ISNS_ATTR_ENTITY_IDENTIFIER, strlen(eid), eid); else length += isns_tlv_set(&tlv, ISNS_ATTR_ISCSI_NAME, strlen(name), name); flags = ISNS_FLAG_CLIENT | ISNS_FLAG_LAST_PDU | ISNS_FLAG_FIRST_PDU; isns_hdr_init(hdr, ISNS_FUNC_DEV_DEREG, length, flags, ++transaction, 0); err = write(isns_fd, buf, length + sizeof(struct isns_hdr)); if (err < 0) log_error("%s %d: %s", __FUNCTION__, __LINE__, strerror(errno)); return 0;}static int recv_hdr(int fd, struct isns_io *rx, struct isns_hdr *hdr){ int err; if (rx->offset < sizeof(*hdr)) { err = read(fd, rx->buf + rx->offset, sizeof(*hdr) - rx->offset); if (err < 0) { if (errno == EAGAIN || errno == EINTR) return -EAGAIN; log_error("header read error %d %d %d %d", fd, err, errno, rx->offset); return -1; } else if (err == 0) return -1; log_debug(1, "header %d %d bytes!", fd, err); rx->offset += err; if (rx->offset < sizeof(*hdr)) { log_debug(1, "header wait %d %d", rx->offset, err); return -EAGAIN; } } return 0;}#define get_hdr_param(hdr, function, length, flags, transaction, sequence) \{ \ function = ntohs(hdr->function); \ length = ntohs(hdr->length); \ flags = ntohs(hdr->flags); \ transaction = ntohs(hdr->transaction); \ sequence = ntohs(hdr->sequence); \}static int recv_pdu(int fd, struct isns_io *rx, struct isns_hdr *hdr){ uint16_t function, length, flags, transaction, sequence; int err; err = recv_hdr(fd, rx, hdr); if (err) return err; /* Now we got a complete header */ get_hdr_param(hdr, function, length, flags, transaction, sequence); log_debug(1, "got a header %x %u %x %u %u", function, length, flags, transaction, sequence); if (length + sizeof(*hdr) > BUFSIZE) { log_error("FIXME we cannot handle this yet %u!", length); return -1; } if (rx->offset < length + sizeof(*hdr)) { err = read(fd, rx->buf + rx->offset, length + sizeof(*hdr) - rx->offset); if (err < 0) { if (errno == EAGAIN || errno == EINTR) return -EAGAIN; log_error("pdu read error %d %d %d %d", fd, err, errno, rx->offset); return -1; } else if (err == 0) return -1; log_debug(1, "pdu %u %u", fd, err); rx->offset += err; if (rx->offset < length + sizeof(*hdr)) { log_error("pdu wait %d %d", rx->offset, err); return -EAGAIN; } } /* Now we got everything. */ rx->offset = 0; return 0;}#define print_unknown_pdu(hdr) \{ \ uint16_t function, length, flags, transaction, sequence; \ get_hdr_param(hdr, function, length, flags, transaction, \ sequence) \ log_error("%s %d: unknown function %x %u %x %u %u", \ __FUNCTION__, __LINE__, \ function, length, flags, transaction, sequence); \}static char *print_scn_pdu(struct isns_hdr *hdr){ struct isns_tlv *tlv = (struct isns_tlv *) hdr->pdu; uint16_t function, length, flags, transaction, sequence; char *name = NULL; get_hdr_param(hdr, function, length, flags, transaction, sequence); while (length) { uint32_t vlen = ntohl(tlv->length); switch (ntohl(tlv->tag)) { case ISNS_ATTR_ISCSI_NAME: log_error("scn name: %u, %s", vlen, (char *) tlv->value); if (!name) name = (char *) tlv->value; break; case ISNS_ATTR_TIMESTAMP:/* log_error("%u : %u : %" PRIx64, ntohl(tlv->tag), vlen, *//* *((uint64_t *) tlv->value)); */ break; case ISNS_ATTR_ISCSI_SCN_BITMAP: log_error("scn bitmap : %x", *((uint32_t *) tlv->value)); break; } length -= (sizeof(*tlv) + vlen); tlv = (struct isns_tlv *) ((char *) tlv->value + vlen); } return name;}static void qry_rsp_handle(struct isns_hdr *hdr){ struct isns_tlv *tlv; uint16_t function, length, flags, transaction, sequence; uint32_t status = (uint32_t) (*hdr->pdu); struct isns_qry_mgmt *mgmt, *n; struct target *target; struct isns_initiator *ini; char *name = NULL; get_hdr_param(hdr, function, length, flags, transaction, sequence); list_for_each_entry_safe(mgmt, n, &qry_list, qlist) { if (mgmt->transaction == transaction) { remque(&mgmt->qlist); goto found; } } log_error("%s %d: transaction not found %u", __FUNCTION__, __LINE__, transaction); return;found: if (status) { log_error("%s %d: error response %u", __FUNCTION__, __LINE__, status); goto free_qry_mgmt; } if (!strlen(mgmt->name)) { log_debug(1, "%s %d: skip %u", __FUNCTION__, __LINE__, transaction); goto free_qry_mgmt; } target = target_lookup_by_name(mgmt->name); if (!target) { log_error("%s %d: invalid tid %s", __FUNCTION__, __LINE__, mgmt->name); goto free_qry_mgmt; } free_all_acl(target); /* skip status */ tlv = (struct isns_tlv *) ((char *) hdr->pdu + 4); length -= 4; while (length) { uint32_t vlen = ntohl(tlv->length); switch (ntohl(tlv->tag)) { case ISNS_ATTR_ISCSI_NAME: name = (char *) tlv->value; break; case ISNS_ATTR_ISCSI_NODE_TYPE: if (ntohl(*(tlv->value)) == ISNS_NODE_INITIATOR && name) { log_error("%s %d: %s", __FUNCTION__, __LINE__, (char *) name); ini = malloc(sizeof(*ini)); if (!ini) goto free_qry_mgmt; snprintf(ini->name, sizeof(ini->name), name); insque(&ini->ilist, &target->isns_head); } else name = NULL; break; default: name = NULL; break; } length -= (sizeof(*tlv) + vlen); tlv = (struct isns_tlv *) ((char *) tlv->value + vlen); }free_qry_mgmt: free(mgmt);}int isns_handle(int is_timeout, int *timeout){ int err; struct isns_io *rx = &isns_rx; struct isns_hdr *hdr = (struct isns_hdr *) rx->buf; uint32_t result; uint16_t function, length, flags, transaction, sequence; char *name = NULL; if (is_timeout) return isns_attr_query(NULL); err = recv_pdu(isns_fd, rx, hdr); if (err) { if (err == -EAGAIN) return err; log_debug(1, "%s %d: close connection %d", __FUNCTION__, __LINE__, isns_fd); close(isns_fd); isns_fd = 0; isns_set_fd(0, scn_listen_fd, scn_fd); return err; } get_hdr_param(hdr, function, length, flags, transaction, sequence); result = ntohl((uint32_t) hdr->pdu[0]); switch (function) { case ISNS_FUNC_DEV_ATTR_REG_RSP: break; case ISNS_FUNC_DEV_ATTR_QRY_RSP: qry_rsp_handle(hdr); break; case ISNS_FUNC_DEV_DEREG_RSP: case ISNS_FUNC_SCN_REG_RSP: break; case ISNS_FUNC_SCN: name = print_scn_pdu(hdr); if (name) { log_error("%s %d: %s", __FUNCTION__, __LINE__, name); isns_attr_query(name); } break; default: print_unknown_pdu(hdr); } return 0;}static int scn_accept_connection(void){ struct sockaddr_storage from; socklen_t slen; int fd, err, opt = 1; slen = sizeof(from); fd = accept(scn_listen_fd, (struct sockaddr *) &from, &slen); if (fd < 0) { log_error("%s %d: accept error %s", __FUNCTION__, __LINE__, strerror(errno)); return -errno; } log_error("Accept scn connection %d", fd); err = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)); if (err) log_error("%s %d: %s\n", __FUNCTION__, __LINE__, strerror(errno)); /* not critical, so ignore. */ scn_fd = fd; isns_set_fd(isns_fd, scn_listen_fd, scn_fd); return 0;}static void send_scn_rsp(char *name, uint16_t transaction){ char buf[1024]; struct isns_hdr *hdr = (struct isns_hdr *) buf; struct isns_tlv *tlv; uint16_t flags, length = 0; int err; memset(buf, 0, sizeof(buf)); *((uint32_t *) hdr->pdu) = 0; tlv = (struct isns_tlv *) ((char *) hdr->pdu + 4); length +=4; length += isns_tlv_set(&tlv, ISNS_ATTR_ISCSI_NAME, strlen(name), name); flags = ISNS_FLAG_CLIENT | ISNS_FLAG_LAST_PDU | ISNS_FLAG_FIRST_PDU; isns_hdr_init(hdr, ISNS_FUNC_SCN_RSP, length, flags, transaction, 0); err = write(scn_fd, buf, length + sizeof(struct isns_hdr)); if (err < 0) log_error("%s %d: %s", __FUNCTION__, __LINE__, strerror(errno));}int isns_scn_handle(int is_accept){ int err; struct isns_io *rx = &scn_rx; struct isns_hdr *hdr = (struct isns_hdr *) rx->buf; uint16_t function, length, flags, transaction, sequence; char *name = NULL; log_error("%s %d: %d", __FUNCTION__, __LINE__, is_accept); if (is_accept) return scn_accept_connection(); err = recv_pdu(scn_fd, rx, hdr); if (err) { if (err == -EAGAIN) return err; log_debug(1, "%s %d: close connection %d", __FUNCTION__, __LINE__, scn_fd); close(scn_fd); scn_fd = 0; isns_set_fd(isns_fd, scn_listen_fd, 0); return err; } get_hdr_param(hdr, function, length, flags, transaction, sequence); switch (function) { case ISNS_FUNC_SCN: name = print_scn_pdu(hdr); break; default: print_unknown_pdu(hdr); } if (name) { send_scn_rsp(name, transaction); isns_attr_query(name); } return 0;}static int scn_init(char *addr){ int fd, opt, err; struct sockaddr_storage lss; socklen_t slen; fd = socket(ss.ss_family, SOCK_STREAM, IPPROTO_TCP); if (fd < 0) { log_error("%s %d: %s\n", __FUNCTION__, __LINE__, strerror(errno)); return -errno; } opt = 1; if (ss.ss_family == AF_INET6) { err = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)); if (err) log_error("%s %d: %s\n", __FUNCTION__, __LINE__, strerror(errno)); goto out; } err = listen(fd, 5); if (err) { log_error("%s %d: %s\n", __FUNCTION__, __LINE__, strerror(errno)); goto out; } slen = sizeof(lss); err = getsockname(fd, (struct sockaddr *) &lss, &slen); if (err) { log_error("%s %d: %s\n", __FUNCTION__, __LINE__, strerror(errno)); goto out; } /* protocol independent way ? */ if (lss.ss_family == AF_INET6) scn_listen_port = ntohs(((struct sockaddr_in6 *) &lss)->sin6_port); else scn_listen_port = ntohs(((struct sockaddr_in *) &lss)->sin_port); log_error("scn listen port %u %d %d\n", scn_listen_port, fd, err);out: if (err) close(fd); else { scn_listen_fd = fd; isns_set_fd(isns_fd, scn_listen_fd, scn_fd); } return err;}int isns_init(char *addr, int isns_ac){ int err; char port[8]; struct addrinfo hints, *res; snprintf(port, sizeof(port), "%d", ISNS_PORT); memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_STREAM; err = getaddrinfo(addr, (char *) &port, &hints, &res); if (err) { log_error("getaddrinfo error %s, %s", gai_strerror(err), addr); return -1; } memcpy(&ss, res->ai_addr, sizeof(ss)); freeaddrinfo(res); rxbuf = calloc(2, BUFSIZE); if (!rxbuf) { log_error("oom!"); return -1; } scn_init(addr); isns_rx.buf = rxbuf; isns_rx.offset = 0; scn_rx.buf = rxbuf + BUFSIZE; scn_rx.offset = 0; use_isns = 1; use_isns_ac = isns_ac; return current_timeout * 1000;}void isns_exit(void){ struct target *target; if (!use_isns) return; list_for_each_entry(target, &targets_list, tlist) isns_scn_deregister(target->name); isns_deregister(); /* we can't receive events any more. */ isns_set_fd(0, 0, 0); if (isns_fd) close(isns_fd); if (scn_listen_fd) close(scn_listen_fd); if (scn_fd) close(scn_fd); free(rxbuf);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -