static ssize_t ibft_attr_show_nic(void *data, int type, char *buf) { struct ibft_kobject *entry = data; struct ibft_nic *nic = entry->nic; void *ibft_loc = entry->header; char *str = buf; __be32 val; if (!nic) return 0; switch (type) { case ISCSI_BOOT_ETH_INDEX: str += sprintf(str, "%d\n", nic->hdr.index); break; case ISCSI_BOOT_ETH_FLAGS: str += sprintf(str, "%d\n", nic->hdr.flags); break; case ISCSI_BOOT_ETH_IP_ADDR: str += sprintf_ipaddr(str, nic->ip_addr); break; case ISCSI_BOOT_ETH_SUBNET_MASK: val = cpu_to_be32(~((1 << (32-nic->subnet_mask_prefix))-1)); str += sprintf(str, "%pI4", &val); break; case ISCSI_BOOT_ETH_PREFIX_LEN: str += sprintf(str, "%d\n", nic->subnet_mask_prefix); break; case ISCSI_BOOT_ETH_ORIGIN: str += sprintf(str, "%d\n", nic->origin); break; case ISCSI_BOOT_ETH_GATEWAY: str += sprintf_ipaddr(str, nic->gateway); break; case ISCSI_BOOT_ETH_PRIMARY_DNS: str += sprintf_ipaddr(str, nic->primary_dns); break; case ISCSI_BOOT_ETH_SECONDARY_DNS: str += sprintf_ipaddr(str, nic->secondary_dns); break; case ISCSI_BOOT_ETH_DHCP: str += sprintf_ipaddr(str, nic->dhcp); break; case ISCSI_BOOT_ETH_VLAN: str += sprintf(str, "%d\n", nic->vlan); break; case ISCSI_BOOT_ETH_MAC: str += sprintf(str, "%pM\n", nic->mac); break; case ISCSI_BOOT_ETH_HOSTNAME: str += sprintf_string(str, nic->hostname_len, (char *)ibft_loc + nic->hostname_off); break; default: break; } return str - buf; };
/* * Routines for parsing the iBFT data to be human readable. */ static ssize_t ibft_attr_show_initiator(struct ibft_kobject *entry, struct ibft_attribute *attr, char *buf) { struct ibft_initiator *initiator = entry->initiator; void *ibft_loc = entry->header; char *str = buf; if (!initiator) return 0; switch (attr->type) { case ibft_init_index: str += sprintf(str, "%d\n", initiator->hdr.index); break; case ibft_init_flags: str += sprintf(str, "%d\n", initiator->hdr.flags); break; case ibft_init_isns_server: str += sprintf_ipaddr(str, initiator->isns_server); break; case ibft_init_slp_server: str += sprintf_ipaddr(str, initiator->slp_server); break; case ibft_init_pri_radius_server: str += sprintf_ipaddr(str, initiator->pri_radius_server); break; case ibft_init_sec_radius_server: str += sprintf_ipaddr(str, initiator->sec_radius_server); break; case ibft_init_initiator_name: str += sprintf_string(str, initiator->initiator_name_len, (char *)ibft_loc + initiator->initiator_name_off); break; default: break; } return str - buf; }
/* * Routines for parsing the iBFT data to be human readable. */ static ssize_t ibft_attr_show_initiator(void *data, int type, char *buf) { struct ibft_kobject *entry = data; struct ibft_initiator *initiator = entry->initiator; void *ibft_loc = entry->header; char *str = buf; if (!initiator) return 0; switch (type) { case ISCSI_BOOT_INI_INDEX: str += sprintf(str, "%d\n", initiator->hdr.index); break; case ISCSI_BOOT_INI_FLAGS: str += sprintf(str, "%d\n", initiator->hdr.flags); break; case ISCSI_BOOT_INI_ISNS_SERVER: str += sprintf_ipaddr(str, initiator->isns_server); break; case ISCSI_BOOT_INI_SLP_SERVER: str += sprintf_ipaddr(str, initiator->slp_server); break; case ISCSI_BOOT_INI_PRI_RADIUS_SERVER: str += sprintf_ipaddr(str, initiator->pri_radius_server); break; case ISCSI_BOOT_INI_SEC_RADIUS_SERVER: str += sprintf_ipaddr(str, initiator->sec_radius_server); break; case ISCSI_BOOT_INI_INITIATOR_NAME: str += sprintf_string(str, initiator->initiator_name_len, (char *)ibft_loc + initiator->initiator_name_off); break; default: break; } return str - buf; }
static ssize_t ibft_attr_show_target(void *data, int type, char *buf) { struct ibft_kobject *entry = data; struct ibft_tgt *tgt = entry->tgt; void *ibft_loc = entry->header; char *str = buf; int i; if (!tgt) return 0; switch (type) { case ISCSI_BOOT_TGT_INDEX: str += sprintf(str, "%d\n", tgt->hdr.index); break; case ISCSI_BOOT_TGT_FLAGS: str += sprintf(str, "%d\n", tgt->hdr.flags); break; case ISCSI_BOOT_TGT_IP_ADDR: str += sprintf_ipaddr(str, tgt->ip_addr); break; case ISCSI_BOOT_TGT_PORT: str += sprintf(str, "%d\n", tgt->port); break; case ISCSI_BOOT_TGT_LUN: for (i = 0; i < 8; i++) str += sprintf(str, "%x", (u8)tgt->lun[i]); str += sprintf(str, "\n"); break; case ISCSI_BOOT_TGT_NIC_ASSOC: str += sprintf(str, "%d\n", tgt->nic_assoc); break; case ISCSI_BOOT_TGT_CHAP_TYPE: str += sprintf(str, "%d\n", tgt->chap_type); break; case ISCSI_BOOT_TGT_NAME: str += sprintf_string(str, tgt->tgt_name_len, (char *)ibft_loc + tgt->tgt_name_off); break; case ISCSI_BOOT_TGT_CHAP_NAME: str += sprintf_string(str, tgt->chap_name_len, (char *)ibft_loc + tgt->chap_name_off); break; case ISCSI_BOOT_TGT_CHAP_SECRET: str += sprintf_string(str, tgt->chap_secret_len, (char *)ibft_loc + tgt->chap_secret_off); break; case ISCSI_BOOT_TGT_REV_CHAP_NAME: str += sprintf_string(str, tgt->rev_chap_name_len, (char *)ibft_loc + tgt->rev_chap_name_off); break; case ISCSI_BOOT_TGT_REV_CHAP_SECRET: str += sprintf_string(str, tgt->rev_chap_secret_len, (char *)ibft_loc + tgt->rev_chap_secret_off); break; default: break; } return str - buf; }
static ssize_t ibft_attr_show_target(struct ibft_kobject *entry, struct ibft_attribute *attr, char *buf) { struct ibft_tgt *tgt = entry->tgt; void *ibft_loc = entry->header; char *str = buf; int i; if (!tgt) return 0; switch (attr->type) { case ibft_tgt_index: str += sprintf(str, "%d\n", tgt->hdr.index); break; case ibft_tgt_flags: str += sprintf(str, "%d\n", tgt->hdr.flags); break; case ibft_tgt_ip_addr: str += sprintf_ipaddr(str, tgt->ip_addr); break; case ibft_tgt_port: str += sprintf(str, "%d\n", tgt->port); break; case ibft_tgt_lun: for (i = 0; i < 8; i++) str += sprintf(str, "%x", (u8)tgt->lun[i]); str += sprintf(str, "\n"); break; case ibft_tgt_nic_assoc: str += sprintf(str, "%d\n", tgt->nic_assoc); break; case ibft_tgt_chap_type: str += sprintf(str, "%d\n", tgt->chap_type); break; case ibft_tgt_name: str += sprintf_string(str, tgt->tgt_name_len, (char *)ibft_loc + tgt->tgt_name_off); break; case ibft_tgt_chap_name: str += sprintf_string(str, tgt->chap_name_len, (char *)ibft_loc + tgt->chap_name_off); break; case ibft_tgt_chap_secret: str += sprintf_string(str, tgt->chap_secret_len, (char *)ibft_loc + tgt->chap_secret_off); break; case ibft_tgt_rev_chap_name: str += sprintf_string(str, tgt->rev_chap_name_len, (char *)ibft_loc + tgt->rev_chap_name_off); break; case ibft_tgt_rev_chap_secret: str += sprintf_string(str, tgt->rev_chap_secret_len, (char *)ibft_loc + tgt->rev_chap_secret_off); break; default: break; } return str - buf; }
static ssize_t ibft_attr_show_nic(struct ibft_kobject *entry, struct ibft_attribute *attr, char *buf) { struct ibft_nic *nic = entry->nic; void *ibft_loc = entry->header; char *str = buf; char *mac; int val; if (!nic) return 0; switch (attr->type) { case ibft_eth_index: str += sprintf(str, "%d\n", nic->hdr.index); break; case ibft_eth_flags: str += sprintf(str, "%d\n", nic->hdr.flags); break; case ibft_eth_ip_addr: str += sprintf_ipaddr(str, nic->ip_addr); break; case ibft_eth_subnet_mask: val = ~((1 << (32-nic->subnet_mask_prefix))-1); str += sprintf(str, NIPQUAD_FMT, (u8)(val >> 24), (u8)(val >> 16), (u8)(val >> 8), (u8)(val)); break; case ibft_eth_origin: str += sprintf(str, "%d\n", nic->origin); break; case ibft_eth_gateway: str += sprintf_ipaddr(str, nic->gateway); break; case ibft_eth_primary_dns: str += sprintf_ipaddr(str, nic->primary_dns); break; case ibft_eth_secondary_dns: str += sprintf_ipaddr(str, nic->secondary_dns); break; case ibft_eth_dhcp: str += sprintf_ipaddr(str, nic->dhcp); break; case ibft_eth_vlan: str += sprintf(str, "%d\n", nic->vlan); break; case ibft_eth_mac: mac = nic->mac; str += sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x\n", (u8)mac[0], (u8)mac[1], (u8)mac[2], (u8)mac[3], (u8)mac[4], (u8)mac[5]); break; case ibft_eth_hostname: str += sprintf_string(str, nic->hostname_len, (char *)ibft_loc + nic->hostname_off); break; default: break; } return str - buf; };
static void handle_dhcp_request(struct dhcp_msg *dhcpmsg) { static char ipbuf[16]; if(dhcpmsg->htype != DHCP_HTYPE_ETH) return; if(dhcpmsg->hlen > NETIF_MAX_HWADDR_LEN) return; ip_addr_t requested_ip; uint8_t *requested_ip_opt = find_dhcp_option(dhcpmsg, DHCP_OPTION_REQUESTED_IP, 4, NULL); if(requested_ip_opt) { memcpy(&requested_ip.addr, requested_ip_opt, 4); } else if(ip_addr_cmp(&requested_ip, IP_ADDR_ANY)) { ip_addr_copy(requested_ip, dhcpmsg->ciaddr); } else { printf("DHCP Server Error: No requested IP\r\n"); send_dhcp_nak(dhcpmsg); return; } /* Test the first 4 octets match */ if(ip4_addr1(&requested_ip) != ip4_addr1(&state->first_client_addr) || ip4_addr2(&requested_ip) != ip4_addr2(&state->first_client_addr) || ip4_addr3(&requested_ip) != ip4_addr3(&state->first_client_addr)) { sprintf_ipaddr(&requested_ip, ipbuf); printf("DHCP Server Error: %s not an allowed IP\r\n", ipbuf); send_dhcp_nak(dhcpmsg); return; } /* Test the last octet is in the MAXCLIENTS range */ int16_t octet_offs = ip4_addr4(&requested_ip) - ip4_addr4(&state->first_client_addr); if(octet_offs < 0 || octet_offs >= state->max_leases) { printf("DHCP Server Error: Address out of range\r\n"); send_dhcp_nak(dhcpmsg); return; } dhcp_lease_t *requested_lease = state->leases + octet_offs; if(requested_lease->expires != 0 && memcmp(requested_lease->hwaddr, dhcpmsg->chaddr,dhcpmsg->hlen)) { printf("DHCP Server Error: Lease for address already taken\r\n"); send_dhcp_nak(dhcpmsg); return; } memcpy(requested_lease->hwaddr, dhcpmsg->chaddr, dhcpmsg->hlen); sprintf_ipaddr(&requested_ip, ipbuf); printf("DHCP lease addr %s assigned to MAC %02x:%02x:%02x:%02x:%02x:%02x\r\n", ipbuf, requested_lease->hwaddr[0], requested_lease->hwaddr[1], requested_lease->hwaddr[2], requested_lease->hwaddr[3], requested_lease->hwaddr[4], requested_lease->hwaddr[5]); requested_lease->expires = DHCPSERVER_LEASE_TIME * configTICK_RATE_HZ; /* Reuse the REQUEST message as the ACK message */ dhcpmsg->op = DHCP_BOOTREPLY; bzero(dhcpmsg->options, DHCP_OPTIONS_LEN); ip_addr_copy(dhcpmsg->yiaddr, requested_ip); uint8_t *opt = (uint8_t *)&dhcpmsg->options; opt = add_dhcp_option_byte(opt, DHCP_OPTION_MESSAGE_TYPE, DHCP_ACK); uint32_t expiry = htonl(DHCPSERVER_LEASE_TIME); opt = add_dhcp_option_bytes(opt, DHCP_OPTION_LEASE_TIME, &expiry, 4); opt = add_dhcp_option_bytes(opt, DHCP_OPTION_SERVER_ID, &state->server_if->ip_addr, 4); opt = add_dhcp_option_bytes(opt, DHCP_OPTION_SUBNET_MASK, &state->server_if->netmask, 4); opt = add_dhcp_option_bytes(opt, DHCP_OPTION_END, NULL, 0); struct netbuf *netbuf = netbuf_new(); netbuf_alloc(netbuf, sizeof(struct dhcp_msg)); netbuf_take(netbuf, dhcpmsg, sizeof(struct dhcp_msg)); netconn_sendto(state->nc, netbuf, IP_ADDR_BROADCAST, 68); netbuf_delete(netbuf); }