1 #include <unistd.h> 2 #include <stddef.h> 3 4 #include <libubox/list.h> 5 6 #include "dhcpv6.h" 7 #include "dhcpv6-pxe.h" 8 9 struct ipv6_pxe_entry { 10 struct list_head list; // List head for linking 11 uint32_t arch; 12 13 // Ready to send 14 struct _o_packed { 15 uint16_t type; // In network endianess 16 uint16_t len; // In network endianess, without /0 17 char payload[]; // Null-terminated here 18 } bootfile_url; 19 }; 20 21 static struct ipv6_pxe_entry* ipv6_pxe_default = NULL; 22 LIST_HEAD(ipv6_pxe_list); 23 24 const struct ipv6_pxe_entry* ipv6_pxe_entry_new(uint32_t arch, const char* url) { 25 size_t url_len = strlen(url); 26 struct ipv6_pxe_entry* ipe = malloc(sizeof(struct ipv6_pxe_entry) + url_len + 1); 27 if (!ipe) 28 return NULL; 29 30 memcpy(ipe->bootfile_url.payload, url, url_len + 1); 31 ipe->bootfile_url.len = htons(url_len); 32 ipe->bootfile_url.type = htons(DHCPV6_OPT_BOOTFILE_URL); 33 34 if (arch == 0xFFFFFFFF) { 35 /* The "default" entry lives outside ipv6_pxe_list; if config 36 * already supplied one (e.g. two boot6 sections without an 37 * arch), free the previous one before replacing it, otherwise 38 * it would leak until ipv6_pxe_clear() runs. */ 39 free(ipv6_pxe_default); 40 ipv6_pxe_default = ipe; 41 } 42 else { 43 ipe->arch = arch; 44 list_add(&ipe->list, &ipv6_pxe_list); 45 } 46 47 return ipe; 48 } 49 50 const struct ipv6_pxe_entry* ipv6_pxe_of_arch(uint16_t arch) { 51 struct ipv6_pxe_entry* entry; 52 list_for_each_entry(entry, &ipv6_pxe_list, list) { 53 if (arch == entry->arch) 54 return entry; 55 } 56 57 return ipv6_pxe_default; 58 } 59 60 void ipv6_pxe_serve_boot_url(uint16_t arch, struct iovec* iov) { 61 const struct ipv6_pxe_entry* entry = ipv6_pxe_of_arch(arch); 62 63 if (entry == NULL) { 64 // No IPv6 PxE bootfile defined 65 iov->iov_base = NULL; 66 iov->iov_len = 0; 67 } 68 else { 69 iov->iov_base = (void*)&(entry->bootfile_url); 70 iov->iov_len = 4 + ntohs(entry->bootfile_url.len); 71 info("Serve IPv6 PxE, arch = %d, url = %s", arch, entry->bootfile_url.payload); 72 } 73 } 74 75 void ipv6_pxe_dump(void) { 76 struct ipv6_pxe_entry* entry; 77 int count = 0; 78 79 if (ipv6_pxe_default) 80 count++; 81 82 list_for_each_entry(entry, &ipv6_pxe_list, list) { 83 count++; 84 } 85 86 if (count) { 87 info("IPv6 PxE URLs:\n"); 88 89 list_for_each_entry(entry, &ipv6_pxe_list, list) 90 info("\tarch %04d = %s\n", entry->arch, entry->bootfile_url.payload); 91 92 if (ipv6_pxe_default) 93 info("\tDefault = %s\n", ipv6_pxe_default->bootfile_url.payload); 94 } 95 } 96 97 void ipv6_pxe_clear(void) { 98 struct ipv6_pxe_entry* entry, * temp; 99 list_for_each_entry_safe(entry, temp, &ipv6_pxe_list, list) { 100 list_del(&entry->list); 101 free(entry); 102 } 103 104 if (ipv6_pxe_default) { 105 free(ipv6_pxe_default); 106 ipv6_pxe_default = NULL; 107 } 108 } 109
This page was automatically generated by LXR 0.3.1. • OpenWrt