📄 iscsi_init.c
字号:
if (servers > CONF_NAMESERVERS_MAX) servers = CONF_NAMESERVERS_MAX; for (i = 0; i < servers; i++) { if (iscsi_if->nameservers[i] == INADDR_NONE) memcpy(&(iscsi_if->nameservers[i]), ext + 1 + 4*i, 4); } break; case 12: /* Host name */ iscsi_bootp_string(iscsi_if->host, ext + 1, *ext, sizeof(iscsi_if->host)); break; case 15: /* Domain name (DNS) */ iscsi_bootp_string(iscsi_if->domain, ext + 1, *ext, sizeof(iscsi_if->domain)); break; case 17: /* Root path */ if (iscsi_if->root_path) kfree(iscsi_if->root_path); if ((iscsi_if->root_path = kmalloc((*ext) + 1, GFP_ATOMIC))) iscsi_bootp_string(iscsi_if->root_path, ext + 1, *ext, *ext + 1); else printk(KERN_ERR "iSCSI-init(iscsi_do_bootp_ext): memory allocation error\n"); break; case 40: /* NIS Domain name (_not_ DNS) */ iscsi_bootp_string(iscsi_if->nisdomain, ext + 1, *ext, sizeof(iscsi_if->nisdomain)); break; }}/* * Receive BOOTP reply. */static int __init iscsi_bootp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt){ struct bootp_pkt *b; struct iphdr *h; struct iscsi_device *d; int len, mt; u8 *end, *ext, *opt; u32 server_id; /* Perform verifications before taking the lock. */ if (skb->pkt_type == PACKET_OTHERHOST) goto drop; if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) return NET_RX_DROP; if (!pskb_may_pull(skb, sizeof(struct iphdr) + sizeof(struct udphdr))) goto drop; b = (struct bootp_pkt *) skb->nh.iph; h = &b->iph; if (h->ihl != 5 || h->version != 4 || h->protocol != IPPROTO_UDP) goto drop; /* Fragments are not supported */ if (h->frag_off & htons(IP_OFFSET | IP_MF)) { if (net_ratelimit()) printk(KERN_ERR "iSCSI-init(iscsi_bootp_recv): ignoring fragmented reply.\n"); goto drop; } if (skb->len < ntohs(h->tot_len)) goto drop; if (ip_fast_csum((char *) h, h->ihl)) goto drop; if (b->udph.source != htons(67) || b->udph.dest != htons(68)) goto drop; if (ntohs(h->tot_len) < ntohs(b->udph.len) + sizeof(struct iphdr)) goto drop; len = ntohs(b->udph.len) - sizeof(struct udphdr); if (len < 300) goto drop; /* Ok the front looks good, make sure we can get at the rest. */ if (!pskb_may_pull(skb, skb->len)) goto drop; b = (struct bootp_pkt*) skb->nh.iph; h = &b->iph; /* One reply at a time, please. */ spin_lock(&bootp_recv_lock); /* Find the iscsi_device that the packet arrived on */ d = iscsi_device_list; while (d && d->dev != dev) d = d->next; if (!d || d->iscsi_if->bootp_got_reply == 1) goto drop_unlock; /* Is it a reply to our BOOTP request? */ if (b->op != BOOTP_REPLY || b->xid != d->xid) { if (net_ratelimit()) printk(KERN_ERR "iSCSI-init(iscsi_bootp_recv): Reply not for us, op[%x] xid[%x]\n", b->op, b->xid); goto drop_unlock; } /* Parse extensions */ if (!memcmp(b->exten, iscsi_bootp_cookie, 4)) { /* Check magic cookie */ end = (u8 *) b + ntohs(b->iph.tot_len); server_id = INADDR_NONE; mt = 0; ext = &b->exten[4]; while (ext < end && *ext != 0xff) { opt = ext++; if (*opt == 0) /* Padding */ continue; ext += *ext + 1; if (ext >= end) break; switch (*opt) { case 53: /* Message type */ if (opt[1]) mt = opt[2]; break; case 54: /* Server ID (IP address) */ if (opt[1] >= 4) memcpy(&server_id, opt + 2, 4); break; } } switch (mt) { case DHCPOFFER: /* While in the process of accepting one offer, * ignore all others. */ if (d->iscsi_if->if_addr != INADDR_NONE) goto drop_unlock; /* Let's accept that offer. */ d->iscsi_if->if_addr = b->your_ip; d->iscsi_if->servaddr = server_id; /* The DHCP indicated server address takes * precedence over the bootp header one if * they are different. */ if ((server_id != INADDR_NONE) && (b->server_ip != server_id)) b->server_ip = d->iscsi_if->servaddr; break; case DHCPACK: /* Yeah! */ break; default: /* Urque. Forget it*/ d->iscsi_if->if_addr = INADDR_NONE; d->iscsi_if->servaddr = INADDR_NONE; goto drop_unlock; } d->iscsi_if->bootp_msgtype = mt; ext = &b->exten[4]; while (ext < end && *ext != 0xff) { opt = ext++; if (*opt == 0) /* Padding */ continue; ext += *ext + 1; if (ext < end) iscsi_do_bootp_ext(opt, d->iscsi_if); } } d->iscsi_if->if_addr = b->your_ip; if (server_id == INADDR_NONE) d->iscsi_if->servaddr = b->server_ip; else d->iscsi_if->servaddr = server_id; if (d->iscsi_if->gateway == INADDR_NONE && b->relay_ip) d->iscsi_if->gateway = b->relay_ip; if (d->iscsi_if->nameservers[0] == INADDR_NONE) d->iscsi_if->nameservers[0] = d->iscsi_if->servaddr; d->iscsi_if->bootp_got_reply = 1;drop_unlock: /* Show's over. Nothing to see here. */ spin_unlock(&bootp_recv_lock);drop: /* Throw the packet out. */ kfree_skb(skb); return 0;} static int __init iscsi_dynamic(struct iscsi_interface *iscsi_if){ int retries = CONF_SEND_RETRIES; struct iscsi_device *d; unsigned long start_jiffies, timeout, jiff; if (!iscsi_device_list) { printk(KERN_ERR "iSCSI-init(iscsi_dynamic): no suitable device found.\n"); return -1; } iscsi_bootp_init(); /* * Send requests and wait, until we get an answer. This loop * seems to be a terrible waste of CPU time, but actually there is * only one process running at all, so we don't need to use any * scheduler functions. */ printk("iSCSI-init: sending DHCP requests ."); start_jiffies = jiffies; d = iscsi_device_list; get_random_bytes(&timeout, sizeof(timeout)); timeout = CONF_BASE_TIMEOUT + (timeout % (unsigned) CONF_TIMEOUT_RANDOM); iscsi_if->bootp_got_reply = 0; for(;;) { iscsi_bootp_send_if(d, jiffies - start_jiffies); jiff = jiffies + (d->next ? CONF_INTER_TIMEOUT : timeout); while (time_before(jiffies, jiff) && !(iscsi_if->bootp_got_reply)) { set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); } /* DHCP isn't done until we get a DHCPACK. */ if (iscsi_if->bootp_got_reply) { if (iscsi_if->bootp_msgtype == DHCPACK) { iscsi_if->dev = d->dev; printk(" OK\n"); break; } else { iscsi_if->bootp_got_reply = 0; printk("."); continue; } } if ((d = d->next)) continue; if (!(--retries)) { printk(" timed out!\n"); break; } d = iscsi_device_list; timeout = timeout CONF_TIMEOUT_MULT; if (timeout > CONF_TIMEOUT_MAX) timeout = CONF_TIMEOUT_MAX; printk("."); } iscsi_bootp_cleanup(); if (!(iscsi_if->bootp_got_reply)) return -1; printk("iSCSI-init: got DHCP answer from %u.%u.%u.%u, my address is %u.%u.%u.%u\n", NIPQUAD(iscsi_if->servaddr), NIPQUAD(iscsi_if->if_addr)); return 0;}static int __init ipconfig(void){ struct iscsi_device *d; struct iscsi_interface *iscsi_if; int retries, i; for (iscsi_if = iscsi_interface_list; iscsi_if; iscsi_if = iscsi_if->next) { for (i = 0; i < CONF_NAMESERVERS_MAX; i++) iscsi_if->nameservers[i] = INADDR_NONE; if (iscsi_open_devs(iscsi_if) < 0) return -1; set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(CONF_POST_OPEN); if (iscsi_if->if_addr == INADDR_NONE) { retries = CONF_OPEN_RETRIES; while (iscsi_dynamic(iscsi_if) < 0 && retries--) { iscsi_close_devs(iscsi_if); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(CONF_PRE_OPEN); printk(KERN_ERR "iSCSI-init(ipconfig): reopening network devices...\n"); if (iscsi_open_devs(iscsi_if) < 0) return -1; set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(CONF_POST_OPEN); } if (iscsi_if->dev == NULL) { if (iscsi_if->if_name) printk(KERN_ERR "iSCSI-init(ipconfig): auto-configuration of network for %s failed.\n", iscsi_if->if_name); else printk(KERN_ERR "iSCSI-init(ipconfig): auto-configuration of network failed.\n"); } } else { for (d = iscsi_device_list; d; d = d->next) if (d->iscsi_if == iscsi_if) iscsi_if->dev = d->dev; } if (iscsi_if->dev) { if (iscsi_setup_if(iscsi_if) == 0) { if (iscsi_if->gateway != INADDR_NONE) iscsi_setup_routes(iscsi_if, 0); printk("iSCSI-init: network interface %s complete:\n", iscsi_if->dev->name); printk(" addr=%u.%u.%u.%u", NIPQUAD(iscsi_if->if_addr)); printk(", mask=%u.%u.%u.%u", NIPQUAD(iscsi_if->if_netmask)); if (iscsi_if->gateway != INADDR_NONE) printk(", gw=%u.%u.%u.%u", NIPQUAD(iscsi_if->gateway)); if (iscsi_if->host[0]) { printk("\n host=%s", iscsi_if->host); if (iscsi_if->domain[0]) printk(", domain=%s", iscsi_if->domain); if (iscsi_if->nisdomain[0]) printk(", nis-domain=%s", iscsi_if->nisdomain); } else { if (iscsi_if->domain[0]) { printk("\n domain=%s", iscsi_if->domain); if (iscsi_if->nisdomain[0]) printk(", nis-domain=%s", iscsi_if->nisdomain); } } printk("\n"); if (iscsi_if->nameservers[0] != INADDR_NONE) { printk(" nameservers=%u.%u.%u.%u", NIPQUAD(iscsi_if->nameservers[0])); for (i = 1; i < CONF_NAMESERVERS_MAX; i++) if (iscsi_if->nameservers[i] != INADDR_NONE) printk(", %u.%u.%u.%u", NIPQUAD(iscsi_if->nameservers[i])); printk("\n"); } if (iscsi_if->root_path) printk(" root-path=%s\n", iscsi_if->root_path); } } iscsi_close_devs(iscsi_if); } return 0;}static char* __init get_cmdline(void){ struct proc_dir_entry *d; char *p, *page, *start = NULL; ssize_t n = 0, count = PROC_BLOCK_SIZE; loff_t pos = 0; int eof = 0; for (d = proc_root.subdir; d; d = d->next) { if (!strcmp(d->name, "cmdline")) { if (!(page = (char*) __get_free_page(GFP_KERNEL))) { printk(KERN_ERR "iSCSI-init(get_cmdline): page allocation error\n"); return NULL; } if (d->get_info) n = d->get_info(page, &start, pos, count); else if (d->read_proc) n = d->read_proc(page, &start, pos, count, &eof, d->data); else { printk(KERN_ERR "iSCSI-init(get_cmdline): no methods available in proc_dir_entry\n"); return NULL; } if ((p = kmalloc(n + 1, GFP_KERNEL))) { *(page + n) = '\0'; strcpy(p, page); } else printk(KERN_ERR "iSCSI-init(get_cmdline): memory allocation error\n"); free_page((unsigned long) page); return p; } } printk(KERN_ERR "iSCSI-init(get_cmdline): no proc_dir_entry found for \"/proc/cmdline\"\n"); return NULL;}static int __init get_ioctldev(void){ struct proc_dir_entry *d; char *page, *start = NULL, *p, *line; char devname[sizeof(ISCSI_IOCTL_DEV) + 12]; ssize_t n = 0, count = PROC_BLOCK_SIZE; loff_t pos = 0; int eof = 0, devnum = 0; for (d = proc_root.subdir; d; d = d->next) { if (!strcmp(d->name, "devices")) { if (!(page = (char*) __get_free_page(GFP_KERNEL))) { printk(KERN_ERR "iSCSI-init(get_ioctldev): page allocation error\n"); return -1; } if (d->get_info) n = d->get_info(page, &start, pos, count); else if (d->read_proc) n = d->read_proc(page, &start, pos, count, &eof, d->data); else { printk(KERN_ERR "iSCSI-init(get_ioctldev): no methods available in proc_dir_entry\n"); return -1; } for (p = page, line = page; p < (page + n); p++) { if (*p == '\n') { *p = '\0'; if (strlen(line) < sizeof(devname) && sscanf(line, "%d %s", &devnum, devname) == 2) { if (!strcmp(devname, ISCSI_IOCTL_DEV)) break; } devnum = 0; line = p + 1; } } free_page((unsigned long) page); if (!devnum) printk(KERN_ERR "iSCSI-init(get_ioctldev): no device \"%s\" was found in \"/proc/devices\"\n", ISCSI_IOCTL_DEV); return devnum; } } printk(KERN_ERR "iSCSI-init(get_ioctldev): no proc_dir_entry found for \"/proc/devices\"\n"); return -1;}static int __init atoi(const char *s){ int i = 0; while (isdigit(*s)) i = i*10 + *(s++) - '0'; return i;} static int __init split_param(char *arg){ int paramlen; for (paramlen = 0; *(arg + paramlen) && !isspace(*(arg + paramlen)); paramlen++); *(arg + paramlen) = '\0'; return paramlen;}static void __init parse_cmdline(void){ #define KEYWORD_ISCSI_INTERFACE "iscsi-if=" #define KEYWORD_ISCSI_INITIATOR "iscsi-initiator=" #define KEYWORD_ISCSI_TARGET "iscsi-target=" #define KEYWORD_ISCSI_TIMEOUT "iscsi-timeout=" int i, cmdlen; char *p1, *p2, *p3, *p4, *p5; struct iscsi_target *p_target, *p2_target; struct iscsi_interface *p_interface, *p2_interface; cmdlen = strlen(cmdline); for (i = 0; i < cmdlen; i++) { if (!strncmp(cmdline + i, KEYWORD_ISCSI_INTERFACE, sizeof(KEYWORD_ISCSI_INTERFACE) - 1)) { i += (sizeof(KEYWORD_ISCSI_INTERFACE) - 1); p4 = cmdline + i; i += split_param(p4); while (p4) { if ((p5 = strchr(p4, ','))) *(p5++) = '\0'; if ((p_interface = kmalloc(sizeof(struct iscsi_interface), GFP_KERNEL))) { memset(p_interface, 0, sizeof(struct iscsi_interface)); p_interface->if_addr = INADDR_NONE; p_interface->if_netmask = INADDR_NONE; p_interface->gateway = INADDR_NONE; p_interface->if_name = p4; if ((p1 = strchr(p4, ':')) && (p2 = strchr(p1 + 1, ':'))) { if ((p3 = strchr(p2 + 1, ':'))) { *(p3++) = '\0'; p_interface->gateway = in_aton(p3); } *(p1++) = '\0', *(p2++) = '\0'; p_interface->if_addr = in_aton(p1); p_interface->if_netmask = in_aton(p2); } /* just make sure we have the same sequence when we rollout the list */ if (iscsi_interface_list) { for (p2_interface = iscsi_interface_list; p2_interface; p2_interface = p2_interface->next) { if (p2_interface->next == NULL) { p2_interface->next = p_interface; break; } } } else iscsi_interface_list = p_interface; } else printk(KERN_ERR "iSCSI-init(parse_parameter): memory allocation error\n"); p4 = p5; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -