📄 iscsid.c
字号:
/* * Copyright (C) 2002-2003 Ardis Technolgies <roman@ardistech.com> * * Released under the terms of the GNU GPL v2.0. */#include <ctype.h>#include <errno.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#include "iscsid.h"static struct iscsi_key login_keys[] = { {"InitiatorName",}, {"InitiatorAlias",}, {"SessionType",}, {"TargetName",}, {NULL, 0, 0, 0, NULL},};char *text_key_find(struct connection *conn, char *searchKey){ char *data, *key, *value; int keylen, datasize; keylen = strlen(searchKey); data = conn->req.data; datasize = conn->req.datasize; while (1) { for (key = data; datasize > 0 && *data != '='; data++, datasize--) ; if (!datasize) return NULL; data++; datasize--; for (value = data; datasize > 0 && *data != 0; data++, datasize--) ; if (!datasize) return NULL; data++; datasize--; if (keylen == value - key - 1 && !strncmp(key, searchKey, keylen)) return value; }}static char *next_key(char **data, int *datasize, char **value){ char *key, *p, *q; int size = *datasize; key = p = *data; for (; size > 0 && *p != '='; p++, size--) ; if (!size) return NULL; *p++ = 0; size--; for (q = p; size > 0 && *p != 0; p++, size--) ; if (!size) return NULL; p++; size--; *data = p; *value = q; *datasize = size; return key;}void text_key_add(struct connection *conn, char *key, char *value){ int keylen = strlen(key); int valuelen = strlen(value); int len = keylen + valuelen + 2; char *buffer; if (!conn->rsp.datasize) { if (!conn->rsp_buffer) conn->rsp_buffer = malloc(INCOMING_BUFSIZE); conn->rsp.data = conn->rsp_buffer; } if (conn->rwsize + len > INCOMING_BUFSIZE) { log_warning("Dropping key (%s=%s)", key, value); return; } buffer = conn->rsp_buffer; buffer += conn->rsp.datasize; conn->rsp.datasize += len; strcpy(buffer, key); buffer += keylen; *buffer++ = '='; strcpy(buffer, value);}static void text_key_add_reject(struct connection *conn, char *key){ text_key_add(conn, key, "Reject");}static int account_empty(u32 tid, int dir){ char pass[ISCSI_NAME_LEN]; memset(pass, 0, sizeof(pass)); return cops->account_query(tid, dir, pass, pass) < 0 ? 1 : 0;}static void text_scan_security(struct connection *conn){ struct iscsi_login_rsp_hdr *rsp = (struct iscsi_login_rsp_hdr *)&conn->rsp.bhs; char *key, *value, *data, *nextValue; int datasize; data = conn->req.data; datasize = conn->req.datasize; while ((key = next_key(&data, &datasize, &value))) { if (!(param_index_by_name(key, login_keys) < 0)) ; else if (!strcmp(key, "AuthMethod")) { do { nextValue = strchr(value, ','); if (nextValue) *nextValue++ = 0; if (!strcmp(value, "None")) { if (!account_empty(conn->tid, AUTH_DIR_INCOMING)) continue; conn->auth_method = AUTH_NONE; text_key_add(conn, key, "None"); break; } else if (!strcmp(value, "CHAP")) { if (account_empty(conn->tid, AUTH_DIR_INCOMING)) continue; conn->auth_method = AUTH_CHAP; text_key_add(conn, key, "CHAP"); break; } } while ((value = nextValue)); if (conn->auth_method == AUTH_UNKNOWN) text_key_add_reject(conn, key); } else text_key_add(conn, key, "NotUnderstood"); } if (conn->auth_method == AUTH_UNKNOWN) { rsp->status_class = ISCSI_STATUS_INITIATOR_ERR; rsp->status_detail = ISCSI_STATUS_AUTH_FAILED; conn->state = STATE_EXIT; }}static void login_security_done(struct connection *conn){ int err; struct iscsi_login_req_hdr *req = (struct iscsi_login_req_hdr *)&conn->req.bhs; struct iscsi_login_rsp_hdr *rsp = (struct iscsi_login_rsp_hdr *)&conn->rsp.bhs; struct session *session; if (!conn->tid) return; if ((session = session_find_name(conn->tid, conn->initiator, req->sid))) { if (!req->sid.id.tsih) { /* do session reinstatement */ session_conns_close(conn->tid, session->sid.id64); session = NULL; } else if (req->sid.id.tsih != session->sid.id.tsih) { /* fail the login */ rsp->status_class = ISCSI_STATUS_INITIATOR_ERR; rsp->status_detail = ISCSI_STATUS_SESSION_NOT_FOUND; conn->state = STATE_EXIT; return; } else if ((err = conn_test(conn)) == -ENOENT) { /* do connection reinstatement */ } /* add a new connection to the session */ conn->session = session; } else { if (req->sid.id.tsih) { /* fail the login */ rsp->status_class = ISCSI_STATUS_INITIATOR_ERR; rsp->status_detail = ISCSI_STATUS_SESSION_NOT_FOUND; conn->state = STATE_EXIT; return; } /* instantiate a new session */ }}static void text_scan_login(struct connection *conn){ char *key, *value, *data; int datasize, idx; struct iscsi_login_rsp_hdr *rsp = (struct iscsi_login_rsp_hdr *)&conn->rsp.bhs; data = conn->req.data; datasize = conn->req.datasize; while ((key = next_key(&data, &datasize, &value))) { if (!(param_index_by_name(key, login_keys) < 0)) ; else if (!strcmp(key, "AuthMethod")) ; else if (!((idx = param_index_by_name(key, session_keys)) < 0)) { int err; unsigned int val; char buf[32]; if (idx == key_max_xmit_data_length) { text_key_add(conn, key, "NotUnderstood"); continue; } if (idx == key_max_recv_data_length) idx = key_max_xmit_data_length; if (param_str_to_val(session_keys, idx, value, &val) < 0) { if (conn->session_param[idx].state == KEY_STATE_START) { text_key_add_reject(conn, key); continue; } else { rsp->status_class = ISCSI_STATUS_INITIATOR_ERR; rsp->status_detail = ISCSI_STATUS_INIT_ERR; conn->state = STATE_EXIT; goto out; } } err = param_check_val(session_keys, idx, &val); err = param_set_val(session_keys, conn->session_param, idx, &val); switch (conn->session_param[idx].state) { case KEY_STATE_START: if (idx == key_max_xmit_data_length) break; memset(buf, 0, sizeof(buf)); param_val_to_str(session_keys, idx, val, buf); text_key_add(conn, key, buf); break; case KEY_STATE_REQUEST: if (val != conn->session_param[idx].val) { rsp->status_class = ISCSI_STATUS_INITIATOR_ERR; rsp->status_detail = ISCSI_STATUS_INIT_ERR; conn->state = STATE_EXIT; log_warning("%s %u %u\n", key, val, conn->session_param[idx].val); goto out; } break; case KEY_STATE_DONE: break; } conn->session_param[idx].state = KEY_STATE_DONE; } else text_key_add(conn, key, "NotUnderstood"); }out: return;}static int text_check_param(struct connection *conn){ struct iscsi_param *p = conn->session_param; char buf[32]; int i, cnt; for (i = 0, cnt = 0; session_keys[i].name; i++) { if (p[i].state == KEY_STATE_START && p[i].val != session_keys[i].def) { switch (conn->state) { case STATE_LOGIN_FULL: case STATE_SECURITY_FULL: if (i == key_max_xmit_data_length) { if (p[i].val > session_keys[i].def) p[i].val = session_keys[i].def; p[i].state = KEY_STATE_DONE; continue; } break; case STATE_LOGIN: if (i == key_max_xmit_data_length) continue; memset(buf, 0, sizeof(buf)); param_val_to_str(session_keys, i, p[i].val, buf); text_key_add(conn, session_keys[i].name, buf); p[i].state = KEY_STATE_REQUEST; break; default: if (i == key_max_xmit_data_length) continue; } cnt++; } } return cnt;}static void login_start(struct connection *conn){ struct iscsi_login_req_hdr *req = (struct iscsi_login_req_hdr *)&conn->req.bhs; struct iscsi_login_rsp_hdr *rsp = (struct iscsi_login_rsp_hdr *)&conn->rsp.bhs; char *name, *alias, *session_type, *target_name; conn->cid = be16_to_cpu(req->cid); conn->sid.id64 = req->sid.id64; if (!conn->sid.id64) { rsp->status_class = ISCSI_STATUS_INITIATOR_ERR; rsp->status_detail = ISCSI_STATUS_MISSING_FIELDS; conn->state = STATE_EXIT; return; } name = text_key_find(conn, "InitiatorName"); if (!name) { rsp->status_class = ISCSI_STATUS_INITIATOR_ERR; rsp->status_detail = ISCSI_STATUS_MISSING_FIELDS; conn->state = STATE_EXIT; return; } conn->initiator = strdup(name); alias = text_key_find(conn, "InitiatorAlias"); session_type = text_key_find(conn, "SessionType"); target_name = text_key_find(conn, "TargetName"); conn->auth_method = -1; conn->session_type = SESSION_NORMAL; if (session_type) { if (!strcmp(session_type, "Discovery")) conn->session_type = SESSION_DISCOVERY; else if (strcmp(session_type, "Normal")) { rsp->status_class = ISCSI_STATUS_INITIATOR_ERR; rsp->status_detail = ISCSI_STATUS_INV_SESSION_TYPE; conn->state = STATE_EXIT; return; } } if (conn->session_type == SESSION_NORMAL) { if (!target_name) { rsp->status_class = ISCSI_STATUS_INITIATOR_ERR; rsp->status_detail = ISCSI_STATUS_MISSING_FIELDS; conn->state = STATE_EXIT; return; } if (!(conn->tid = target_find_by_name(target_name)) || cops->initiator_access(conn->tid, conn->fd) < 0) { rsp->status_class = ISCSI_STATUS_INITIATOR_ERR; rsp->status_detail = ISCSI_STATUS_TGT_NOT_FOUND;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -