From: Kun H. <kun...@gm...> - 2010-01-29 01:03:09
|
Tested working with a slight issue fixed: > +static int __plain_target_redirect(u32 tid, char *dest, int update) > +{ > + struct target *target; > + char *a = dest, *p = dest + strlen(dest); > + > + if (!tid || !dest) > + return -EINVAL; > + > + target = target_find_by_id(tid); > + if (!target) { > + log_error("can't find target: %d", tid); > + return -ENOENT; > + } > + > + if (strlen(a)) { > + while(isspace(*a)) > + a++; > + > + while(strlen(a) && isspace(*p)) > + *(p--) = '\0'; > + > + if ((p = strrchr(a, ']'))) should be : if (*(p = strrchr(a, ']'))) > + p = strchrnul(p, ':'); > + else > + p = strchrnul(a, ':'); > + > + if (*p) { > + *(p++) = '\0'; > + if (!atoi(p)) > + return -EINVAL; > + } > + > + if (!is_addr_valid(a)) > + return -EINVAL; > + > + log_warning("target %s redirected to %s:%s", target->name, a, > + strlen(p) ? p : "3260"); > + } else > + log_warning("target redirection for %s cleared", target->name); > + > + snprintf(target->redirect.addr, sizeof(target->redirect.addr), "%s", a); > + snprintf(target->redirect.port, sizeof(target->redirect.port), "%s", p); > + > + return 0; Thanks! - Kun On Thu, Jan 28, 2010 at 3:21 PM, Ross S. W. Walker <RW...@me...> wrote: > Kun Huang [mailto:kun...@gm...] wrote: >> >> Hi, >> >> Addressed Arne and Ross's newest updates. >> >> Tested with inititator. >> >> Did not find easy way to reuse plain.c to do ip validation. > > Ok here is what I think is the final product. > > Please review and let me know. > > -Ross > > Index: ietadm.c > =================================================================== > --- ietadm.c (revision 285) > +++ ietadm.c (working copy) > @@ -28,6 +28,7 @@ > #define SET_CONNECTION (1 << 2) > #define SET_LUNIT (1 << 3) > #define SET_USER (1 << 4) > +#define SET_REDIRECT (1 << 5) > > typedef int (user_handle_fn_t)(struct ietadm_req *req, char *user, char *pass); > > @@ -47,6 +48,7 @@ > {"sid", required_argument, NULL, 's'}, > {"cid", required_argument, NULL, 'c'}, > {"lun", required_argument, NULL, 'l'}, > + {"redirect", required_argument, NULL, 'r'}, > {"params", required_argument, NULL, 'p'}, > {"user", no_argument, NULL, 'u'}, > {"version", no_argument, NULL, 'v'}, > @@ -112,6 +114,15 @@ > [OutgoingUser].\n\ > If you don't specify a target (omit --tid option),\n\ > you delete the account for discovery sessions.\n\ > + --op update --tid=[id] --redirect=[dest]\n\ > + redirect login to target with tid [id] to portal\n\ > + [dest]. Discovery sessions will not be impacted,\n\ > + but normal sessions will be redirected before\n\ > + security negotiation. The destination should be\n\ > + specified using the format:\n\ > + <ip_addr>[:port]\n\ > + IPv6 addresses need to be enclosed in [] brackets\n\ > + To clear, provide an empty string\n\ > --version display version and exit\n\ > --help display this help and exit\n\ > \n\ > @@ -330,9 +341,14 @@ > req.rcmnd = C_TRGT_DEL; > break; > case OP_UPDATE: > - req.rcmnd = C_TRGT_UPDATE; > - if ((err = parse_trgt_params(&req.u.trgt, params)) < 0) > - goto out; > + if (set & SET_REDIRECT) { > + req.rcmnd = C_TRGT_REDIRECT; > + strncpy(req.u.redir.dest, params, sizeof(req.u.redir.dest) - 1); > + } else { > + req.rcmnd = C_TRGT_UPDATE; > + if ((err = parse_trgt_params(&req.u.trgt, params)) < 0) > + goto out; > + } > break; > case OP_SHOW: > req.rcmnd = C_TRGT_SHOW; > @@ -682,7 +698,7 @@ > u64 sid = 0; > char *params = NULL; > > - while ((ch = getopt_long(argc, argv, "o:t:s:c:l:p:uvh", > + while ((ch = getopt_long(argc, argv, "o:t:s:c:l:r:p:uvh", > long_options, &longindex)) >= 0) { > switch (ch) { > case 'o': > @@ -707,6 +723,10 @@ > case 'p': > params = optarg; > break; > + case 'r': > + set |= SET_REDIRECT; > + params = optarg; > + break; > case 'u': > set |= SET_USER; > break; > Index: plain.c > =================================================================== > --- plain.c (revision 285) > +++ plain.c (working copy) > @@ -43,6 +43,31 @@ > char *password; > }; > > +int is_addr_valid(char *addr) > +{ > + struct in_addr ia; > + struct in6_addr ia6; > + char tmp[NI_MAXHOST + 1], *p = tmp, *q; > + > + if (inet_pton(AF_INET, addr, &ia) == 1) > + return 1; > + > + snprintf(tmp, sizeof(tmp), "%s", addr); > + > + if (*p == '[') { > + p++; > + q = p + strlen(p); > + if (*q != ']') > + return 0; > + *q = '\0'; > + } > + > + if (inet_pton(AF_INET6, p, &ia6) == 1) > + return 1; > + > + return 0; > +} > + > /* this is the orignal Ardis code. */ > static char *target_sep_string(char **pp) > { > @@ -476,6 +501,57 @@ > * Main configuration code > */ > > +static int __plain_target_redirect(u32 tid, char *dest, int update) > +{ > + struct target *target; > + char *a = dest, *p = dest + strlen(dest); > + > + if (!tid || !dest) > + return -EINVAL; > + > + target = target_find_by_id(tid); > + if (!target) { > + log_error("can't find target: %d", tid); > + return -ENOENT; > + } > + > + if (strlen(a)) { > + while(isspace(*a)) > + a++; > + > + while(strlen(a) && isspace(*p)) > + *(p--) = '\0'; > + > + if ((p = strrchr(a, ']'))) > + p = strchrnul(p, ':'); > + else > + p = strchrnul(a, ':'); > + > + if (*p) { > + *(p++) = '\0'; > + if (!atoi(p)) > + return -EINVAL; > + } > + > + if (!is_addr_valid(a)) > + return -EINVAL; > + > + log_warning("target %s redirected to %s:%s", target->name, a, > + strlen(p) ? p : "3260"); > + } else > + log_warning("target redirection for %s cleared", target->name); > + > + snprintf(target->redirect.addr, sizeof(target->redirect.addr), "%s", a); > + snprintf(target->redirect.port, sizeof(target->redirect.port), "%s", p); > + > + return 0; > +} > + > +static int plain_target_redirect(u32 tid, char *dest) > +{ > + return __plain_target_redirect(tid, dest, 1); > +} > + > static int __plain_target_create(u32 *tid, char *name, int update) > { > int err; > @@ -735,4 +811,5 @@ > .account_list = plain_account_list, > .initiator_allow = plain_initiator_allow, > .target_allow = plain_target_allow, > + .target_redirect = plain_target_redirect, > }; > Index: ietadm.h > =================================================================== > --- ietadm.h (revision 285) > +++ ietadm.h (working copy) > @@ -33,11 +33,16 @@ > char args[ISCSI_ARGS_LEN]; > }; > > +struct msg_redir { > + char dest[NI_MAXHOST + NI_MAXSERV + 4]; > +}; > + > enum ietadm_cmnd { > C_TRGT_NEW, > C_TRGT_DEL, > C_TRGT_UPDATE, > C_TRGT_SHOW, > + C_TRGT_REDIRECT, > > C_SESS_NEW, > C_SESS_DEL, > @@ -79,6 +84,7 @@ > struct msg_trgt trgt; > struct msg_acnt acnt; > struct msg_lunit lunit; > + struct msg_redir redir; > } u; > }; > > Index: config.h > =================================================================== > --- config.h (revision 285) > +++ config.h (working copy) > @@ -16,6 +16,7 @@ > int (*account_list) (u32, int, u32 *, u32 *, char *, size_t); > int (*initiator_allow) (u32, int, char *); > int (*target_allow) (u32, struct sockaddr *); > + int (*target_redirect) (u32, char *); > }; > > extern struct config_operations *cops; > Index: isns.c > =================================================================== > --- isns.c (revision 285) > +++ isns.c (working copy) > @@ -60,7 +60,7 @@ > static uint16_t transaction; > static uint32_t current_timeout = 30; /* seconds */ > static char eid[ISCSI_NAME_LEN]; > -static uint8_t ip[16]; /* IET supoprts only one portal */ > +static uint8_t ip[16]; /* IET supports only one portal */ > static struct sockaddr_storage ss; > > int isns_scn_allow(uint32_t tid, char *name) > Index: iscsid.c > =================================================================== > --- iscsid.c (revision 285) > +++ iscsid.c (working copy) > @@ -426,7 +426,8 @@ > conn->auth_method = -1; > conn->session_type = SESSION_NORMAL; > > - getsockname(conn->fd, (struct sockaddr *) &ss, &slen); > + if (getsockname(conn->fd, (struct sockaddr *) &ss, &slen)) > + log_error("%s: Failed to get local address.", __FUNCTION__); > > if (session_type) { > if (!strcmp(session_type, "Discovery")) > @@ -454,6 +455,21 @@ > return; > } > > + if (target_redirected(target, conn, (struct sockaddr *) &ss)) { > + struct iscsi_login_rsp_hdr *rsp = > + (struct iscsi_login_rsp_hdr *)&conn->rsp.bhs; > + > + log_debug(1, "redirected target %s login to %s:%s", > + target->name, target->redirect.addr, > + strlen(target->redirect.port) ? > + target->redirect.port : "3260"); > + > + rsp->status_class = ISCSI_STATUS_REDIRECT; > + rsp->status_detail = ISCSI_STATUS_TGT_MOVED_TEMP; > + conn->state = STATE_EXIT; > + return; > + } > + > conn->tid = target->tid; > > if (target->max_nr_sessions && > @@ -817,7 +833,7 @@ > } > cmnd_exec_login(conn); > login_rsp = (struct iscsi_login_rsp_hdr *) &conn->rsp.bhs; > - if (login_rsp->status_class) > + if (login_rsp->status_class && login_rsp->status_class != ISCSI_STATUS_REDIRECT) > conn_free_rsp_buf_list(conn); > break; > case ISCSI_OP_TEXT_CMD: > Index: iscsid.h > =================================================================== > --- iscsid.h (revision 285) > +++ iscsid.h (working copy) > @@ -10,6 +10,7 @@ > #include <search.h> > #include <sys/socket.h> > #include <sys/types.h> > +#include <netdb.h> > > #include "types.h" > #include "iscsi_hdr.h" > @@ -154,6 +155,11 @@ > char name[ISCSI_NAME_LEN]; > char *alias; > > + struct redirect_addr { > + char addr[NI_MAXHOST + 1]; > + char port[NI_MAXSERV + 1]; > + } redirect; > + > int max_nr_sessions; > int nr_sessions; > > @@ -208,6 +214,7 @@ > extern struct __qelem targets_list; > extern int target_add(u32 *, char *); > extern int target_del(u32); > +extern int target_redirected(struct target *, struct connection *, struct sockaddr *); > extern struct target * target_find_by_name(const char *name); > extern struct target * target_find_by_id(u32); > extern void target_list_build(struct connection *, char *); > Index: message.c > =================================================================== > --- message.c (revision 285) > +++ message.c (working copy) > @@ -72,6 +72,9 @@ > err = ki->param_get(req->tid, req->sid, key_target, > req->u.trgt.target_param); > break; > + case C_TRGT_REDIRECT: > + err = cops->target_redirect(req->tid, req->u.redir.dest); > + break; > > case C_SESS_NEW: > case C_SESS_DEL: > Index: target.c > =================================================================== > --- target.c (revision 285) > +++ target.c (working copy) > @@ -266,3 +266,35 @@ > free(target); > return err; > } > + > +int target_redirected(struct target *target, struct connection *conn, struct sockaddr *sa) > +{ > + char tmp[NI_MAXHOST + 1]; > + char addr[NI_MAXHOST + 3]; > + char redirect[NI_MAXHOST + NI_MAXSERV + 4]; > + > + if (!strlen(target->redirect.addr)) > + return 0; > + > + if (getnameinfo(sa, (sa->sa_family == AF_INET) ? > + sizeof(struct sockaddr_in) : > + sizeof(struct sockaddr_in6), > + tmp, sizeof(tmp), NULL, 0, > + NI_NUMERICHOST)) > + return 0; > + > + if (sa->sa_family == AF_INET6) > + snprintf(addr, sizeof(addr), "[%s]", tmp); > + else > + snprintf(addr, sizeof(addr), "%s", tmp); > + > + snprintf(redirect, sizeof(redirect), "%s:%s", target->redirect.addr, > + strlen(target->redirect.port) ? target->redirect.port : "3260"); > + > + if (strcmp(target->redirect.addr, addr)) { > + text_key_add(conn, "TargetAddress", redirect); > + return 1; > + } > + > + return 0; > +} > > ______________________________________________________________________ > This e-mail, and any attachments thereto, is intended only for use by > the addressee(s) named herein and may contain legally privileged > and/or confidential information. If you are not the intended recipient > of this e-mail, you are hereby notified that any dissemination, > distribution or copying of this e-mail, and any attachments thereto, > is strictly prohibited. If you have received this e-mail in error, > please immediately notify the sender and permanently delete the > original and any copy or printout thereof. > > |