net.c 55 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159
  1. /*
  2. * GRUB -- GRand Unified Bootloader
  3. * Copyright (C) 2010,2011,2012,2013 Free Software Foundation, Inc.
  4. *
  5. * GRUB is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * GRUB is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include <grub/net.h>
  19. #include <grub/net/netbuff.h>
  20. #include <grub/time.h>
  21. #include <grub/file.h>
  22. #include <grub/i18n.h>
  23. #include <grub/mm.h>
  24. #include <grub/misc.h>
  25. #include <grub/dl.h>
  26. #include <grub/command.h>
  27. #include <grub/env.h>
  28. #include <grub/net/ethernet.h>
  29. #include <grub/net/arp.h>
  30. #include <grub/net/ip.h>
  31. #include <grub/loader.h>
  32. #include <grub/bufio.h>
  33. #include <grub/kernel.h>
  34. #include <grub/safemath.h>
  35. GRUB_MOD_LICENSE ("GPLv3+");
  36. char *grub_net_default_server;
  37. struct grub_net_route *grub_net_routes = NULL;
  38. struct grub_net_network_level_interface *grub_net_network_level_interfaces = NULL;
  39. struct grub_net_card *grub_net_cards = NULL;
  40. struct grub_net_network_level_protocol *grub_net_network_level_protocols = NULL;
  41. static struct grub_fs grub_net_fs;
  42. struct grub_net_link_layer_entry {
  43. int avail;
  44. grub_net_network_level_address_t nl_address;
  45. grub_net_link_level_address_t ll_address;
  46. };
  47. #define LINK_LAYER_CACHE_SIZE 256
  48. static struct grub_net_link_layer_entry *
  49. link_layer_find_entry (const grub_net_network_level_address_t *proto,
  50. const struct grub_net_card *card)
  51. {
  52. unsigned i;
  53. if (!card->link_layer_table)
  54. return NULL;
  55. for (i = 0; i < LINK_LAYER_CACHE_SIZE; i++)
  56. {
  57. if (card->link_layer_table[i].avail == 1
  58. && grub_net_addr_cmp (&card->link_layer_table[i].nl_address,
  59. proto) == 0)
  60. return &card->link_layer_table[i];
  61. }
  62. return NULL;
  63. }
  64. void
  65. grub_net_link_layer_add_address (struct grub_net_card *card,
  66. const grub_net_network_level_address_t *nl,
  67. const grub_net_link_level_address_t *ll,
  68. int override)
  69. {
  70. struct grub_net_link_layer_entry *entry;
  71. /* Check if the sender is in the cache table. */
  72. entry = link_layer_find_entry (nl, card);
  73. /* Update sender hardware address. */
  74. if (entry && override)
  75. grub_memcpy (&entry->ll_address, ll, sizeof (entry->ll_address));
  76. if (entry)
  77. return;
  78. /* Add sender to cache table. */
  79. if (card->link_layer_table == NULL)
  80. {
  81. card->link_layer_table = grub_calloc (LINK_LAYER_CACHE_SIZE,
  82. sizeof (card->link_layer_table[0]));
  83. if (card->link_layer_table == NULL)
  84. return;
  85. }
  86. entry = &(card->link_layer_table[card->new_ll_entry]);
  87. entry->avail = 1;
  88. grub_memcpy (&entry->ll_address, ll, sizeof (entry->ll_address));
  89. grub_memcpy (&entry->nl_address, nl, sizeof (entry->nl_address));
  90. card->new_ll_entry++;
  91. if (card->new_ll_entry == LINK_LAYER_CACHE_SIZE)
  92. card->new_ll_entry = 0;
  93. }
  94. int
  95. grub_net_link_layer_resolve_check (struct grub_net_network_level_interface *inf,
  96. const grub_net_network_level_address_t *proto_addr)
  97. {
  98. struct grub_net_link_layer_entry *entry;
  99. if (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4
  100. && proto_addr->ipv4 == 0xffffffff)
  101. return 1;
  102. entry = link_layer_find_entry (proto_addr, inf->card);
  103. if (entry)
  104. return 1;
  105. return 0;
  106. }
  107. grub_err_t
  108. grub_net_link_layer_resolve (struct grub_net_network_level_interface *inf,
  109. const grub_net_network_level_address_t *proto_addr,
  110. grub_net_link_level_address_t *hw_addr)
  111. {
  112. struct grub_net_link_layer_entry *entry;
  113. grub_err_t err;
  114. if ((proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4
  115. && proto_addr->ipv4 == 0xffffffff)
  116. || proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV
  117. || (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6
  118. && proto_addr->ipv6[0] == grub_be_to_cpu64_compile_time (0xff02ULL
  119. << 48)
  120. && proto_addr->ipv6[1] == (grub_be_to_cpu64_compile_time (1))))
  121. {
  122. hw_addr->type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
  123. grub_memset (hw_addr->mac, -1, 6);
  124. return GRUB_ERR_NONE;
  125. }
  126. if (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6
  127. && ((grub_be_to_cpu64 (proto_addr->ipv6[0]) >> 56) == 0xff))
  128. {
  129. hw_addr->type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
  130. hw_addr->mac[0] = 0x33;
  131. hw_addr->mac[1] = 0x33;
  132. hw_addr->mac[2] = ((grub_be_to_cpu64 (proto_addr->ipv6[1]) >> 24) & 0xff);
  133. hw_addr->mac[3] = ((grub_be_to_cpu64 (proto_addr->ipv6[1]) >> 16) & 0xff);
  134. hw_addr->mac[4] = ((grub_be_to_cpu64 (proto_addr->ipv6[1]) >> 8) & 0xff);
  135. hw_addr->mac[5] = ((grub_be_to_cpu64 (proto_addr->ipv6[1]) >> 0) & 0xff);
  136. return GRUB_ERR_NONE;
  137. }
  138. /* Check cache table. */
  139. entry = link_layer_find_entry (proto_addr, inf->card);
  140. if (entry)
  141. {
  142. *hw_addr = entry->ll_address;
  143. return GRUB_ERR_NONE;
  144. }
  145. switch (proto_addr->type)
  146. {
  147. case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4:
  148. err = grub_net_arp_send_request (inf, proto_addr);
  149. break;
  150. case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6:
  151. err = grub_net_icmp6_send_request (inf, proto_addr);
  152. break;
  153. case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV:
  154. return grub_error (GRUB_ERR_BUG, "shouldn't reach here");
  155. default:
  156. return grub_error (GRUB_ERR_BUG,
  157. "unsupported address type %d", proto_addr->type);
  158. }
  159. if (err)
  160. return err;
  161. entry = link_layer_find_entry (proto_addr, inf->card);
  162. if (entry)
  163. {
  164. *hw_addr = entry->ll_address;
  165. return GRUB_ERR_NONE;
  166. }
  167. return grub_error (GRUB_ERR_TIMEOUT,
  168. N_("timeout: could not resolve hardware address"));
  169. }
  170. void
  171. grub_net_card_unregister (struct grub_net_card *card)
  172. {
  173. struct grub_net_network_level_interface *inf, *next;
  174. FOR_NET_NETWORK_LEVEL_INTERFACES_SAFE(inf, next)
  175. if (inf->card == card)
  176. grub_net_network_level_interface_unregister (inf);
  177. if (card->opened)
  178. {
  179. if (card->driver->close)
  180. card->driver->close (card);
  181. card->opened = 0;
  182. }
  183. grub_list_remove (GRUB_AS_LIST (card));
  184. }
  185. static struct grub_net_slaac_mac_list *
  186. grub_net_ipv6_get_slaac (struct grub_net_card *card,
  187. const grub_net_link_level_address_t *hwaddr)
  188. {
  189. struct grub_net_slaac_mac_list *slaac;
  190. char *ptr;
  191. grub_size_t sz;
  192. for (slaac = card->slaac_list; slaac; slaac = slaac->next)
  193. if (grub_net_hwaddr_cmp (&slaac->address, hwaddr) == 0)
  194. return slaac;
  195. slaac = grub_zalloc (sizeof (*slaac));
  196. if (!slaac)
  197. return NULL;
  198. if (grub_add (grub_strlen (card->name),
  199. (GRUB_NET_MAX_STR_HWADDR_LEN + sizeof (":slaac")), &sz))
  200. {
  201. grub_free (slaac);
  202. grub_error (GRUB_ERR_OUT_OF_RANGE,
  203. "overflow detected while obtaining size of slaac name");
  204. return NULL;
  205. }
  206. slaac->name = grub_malloc (sz);
  207. if (slaac->name == NULL)
  208. {
  209. grub_free (slaac);
  210. return NULL;
  211. }
  212. ptr = grub_stpcpy (slaac->name, card->name);
  213. if (grub_net_hwaddr_cmp (&card->default_address, hwaddr) != 0)
  214. {
  215. ptr = grub_stpcpy (ptr, ":");
  216. grub_net_hwaddr_to_str (hwaddr, ptr);
  217. ptr += grub_strlen (ptr);
  218. }
  219. ptr = grub_stpcpy (ptr, ":slaac");
  220. grub_memcpy (&slaac->address, hwaddr, sizeof (slaac->address));
  221. slaac->next = card->slaac_list;
  222. card->slaac_list = slaac;
  223. return slaac;
  224. }
  225. static void
  226. grub_net_network_level_interface_register (struct grub_net_network_level_interface *inter);
  227. static struct grub_net_network_level_interface *
  228. grub_net_add_addr_real (char *name,
  229. struct grub_net_card *card,
  230. const grub_net_network_level_address_t *addr,
  231. const grub_net_link_level_address_t *hwaddress,
  232. grub_net_interface_flags_t flags)
  233. {
  234. struct grub_net_network_level_interface *inter;
  235. inter = grub_zalloc (sizeof (*inter));
  236. if (!inter)
  237. return NULL;
  238. inter->name = name;
  239. grub_memcpy (&(inter->address), addr, sizeof (inter->address));
  240. grub_memcpy (&(inter->hwaddress), hwaddress, sizeof (inter->hwaddress));
  241. inter->flags = flags;
  242. inter->card = card;
  243. inter->dhcp_ack = NULL;
  244. inter->dhcp_acklen = 0;
  245. grub_net_network_level_interface_register (inter);
  246. return inter;
  247. }
  248. struct grub_net_network_level_interface *
  249. grub_net_add_addr (const char *name,
  250. struct grub_net_card *card,
  251. const grub_net_network_level_address_t *addr,
  252. const grub_net_link_level_address_t *hwaddress,
  253. grub_net_interface_flags_t flags)
  254. {
  255. char *name_dup = grub_strdup (name);
  256. struct grub_net_network_level_interface *ret;
  257. if (!name_dup)
  258. return NULL;
  259. ret = grub_net_add_addr_real (name_dup, card, addr, hwaddress, flags);
  260. if (!ret)
  261. grub_free (name_dup);
  262. return ret;
  263. }
  264. struct grub_net_network_level_interface *
  265. grub_net_ipv6_get_link_local (struct grub_net_card *card,
  266. const grub_net_link_level_address_t *hwaddr)
  267. {
  268. struct grub_net_network_level_interface *inf;
  269. char *name;
  270. char *ptr;
  271. grub_net_network_level_address_t addr;
  272. grub_size_t sz;
  273. addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
  274. addr.ipv6[0] = grub_cpu_to_be64_compile_time (0xfe80ULL << 48);
  275. addr.ipv6[1] = grub_net_ipv6_get_id (hwaddr);
  276. addr.option = 0;
  277. FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
  278. {
  279. if (inf->card == card
  280. && grub_net_hwaddr_cmp (&inf->hwaddress, hwaddr) == 0
  281. && grub_net_addr_cmp (&inf->address, &addr) == 0)
  282. return inf;
  283. }
  284. if (grub_add (grub_strlen (card->name),
  285. (GRUB_NET_MAX_STR_HWADDR_LEN + sizeof (":link")), &sz))
  286. {
  287. grub_error (GRUB_ERR_OUT_OF_RANGE,
  288. "overflow detected while obtaining size of link name");
  289. return NULL;
  290. }
  291. name = grub_malloc (sz);
  292. if (!name)
  293. return NULL;
  294. ptr = grub_stpcpy (name, card->name);
  295. if (grub_net_hwaddr_cmp (&card->default_address, hwaddr) != 0)
  296. {
  297. ptr = grub_stpcpy (ptr, ":");
  298. grub_net_hwaddr_to_str (hwaddr, ptr);
  299. ptr += grub_strlen (ptr);
  300. }
  301. ptr = grub_stpcpy (ptr, ":link");
  302. return grub_net_add_addr_real (name, card, &addr, hwaddr, 0);
  303. }
  304. /* FIXME: allow to specify mac address. */
  305. static grub_err_t
  306. grub_cmd_ipv6_autoconf (struct grub_command *cmd __attribute__ ((unused)),
  307. int argc, char **args)
  308. {
  309. struct grub_net_card *card;
  310. struct grub_net_network_level_interface **ifaces;
  311. grub_size_t ncards = 0;
  312. unsigned j = 0;
  313. int interval;
  314. grub_err_t err;
  315. struct grub_net_slaac_mac_list **slaacs;
  316. FOR_NET_CARDS (card)
  317. {
  318. if (argc > 0 && grub_strcmp (card->name, args[0]) != 0)
  319. continue;
  320. ncards++;
  321. }
  322. ifaces = grub_calloc (ncards, sizeof (ifaces[0]));
  323. slaacs = grub_calloc (ncards, sizeof (slaacs[0]));
  324. if (!ifaces || !slaacs)
  325. {
  326. grub_free (ifaces);
  327. grub_free (slaacs);
  328. return grub_errno;
  329. }
  330. FOR_NET_CARDS (card)
  331. {
  332. if (argc > 0 && grub_strcmp (card->name, args[0]) != 0)
  333. continue;
  334. ifaces[j] = grub_net_ipv6_get_link_local (card, &card->default_address);
  335. if (!ifaces[j])
  336. {
  337. grub_free (ifaces);
  338. grub_free (slaacs);
  339. return grub_errno;
  340. }
  341. slaacs[j] = grub_net_ipv6_get_slaac (card, &card->default_address);
  342. if (!slaacs[j])
  343. {
  344. grub_free (ifaces);
  345. grub_free (slaacs);
  346. return grub_errno;
  347. }
  348. j++;
  349. }
  350. for (interval = 200; interval < 10000; interval *= 2)
  351. {
  352. int done = 1;
  353. for (j = 0; j < ncards; j++)
  354. {
  355. if (slaacs[j]->slaac_counter)
  356. continue;
  357. err = grub_net_icmp6_send_router_solicit (ifaces[j]);
  358. if (err)
  359. err = GRUB_ERR_NONE;
  360. done = 0;
  361. }
  362. if (done)
  363. break;
  364. grub_net_poll_cards (interval, 0);
  365. }
  366. err = GRUB_ERR_NONE;
  367. for (j = 0; j < ncards; j++)
  368. {
  369. if (slaacs[j]->slaac_counter)
  370. continue;
  371. err = grub_error (GRUB_ERR_FILE_NOT_FOUND,
  372. N_("couldn't autoconfigure %s"),
  373. ifaces[j]->card->name);
  374. }
  375. grub_free (ifaces);
  376. grub_free (slaacs);
  377. return err;
  378. }
  379. static int
  380. parse_ip (const char *val, grub_uint32_t *ip, const char **rest)
  381. {
  382. grub_uint32_t newip = 0;
  383. int i;
  384. const char *ptr = val;
  385. for (i = 0; i < 4; i++)
  386. {
  387. unsigned long t;
  388. t = grub_strtoul (ptr, &ptr, 0);
  389. if (grub_errno)
  390. {
  391. grub_errno = GRUB_ERR_NONE;
  392. return 0;
  393. }
  394. if (*ptr != '.' && i == 0)
  395. {
  396. newip = t;
  397. break;
  398. }
  399. if (t & ~0xff)
  400. return 0;
  401. newip >>= 8;
  402. newip |= (t << 24);
  403. if (i != 3 && *ptr != '.')
  404. return 0;
  405. ptr++;
  406. }
  407. *ip = grub_cpu_to_le32 (newip);
  408. if (rest)
  409. *rest = (ptr - 1);
  410. return 1;
  411. }
  412. static int
  413. parse_ip6 (const char *val, grub_uint64_t *ip, const char **rest)
  414. {
  415. grub_uint16_t newip[8];
  416. const char *ptr = val;
  417. int word, quaddot = -1;
  418. bool bracketed = false;
  419. if (ptr[0] == '[')
  420. {
  421. bracketed = true;
  422. ptr++;
  423. }
  424. if (ptr[0] == ':' && ptr[1] != ':')
  425. return 0;
  426. if (ptr[0] == ':')
  427. ptr++;
  428. for (word = 0; word < 8; word++)
  429. {
  430. unsigned long t;
  431. if (*ptr == ':')
  432. {
  433. quaddot = word;
  434. word--;
  435. ptr++;
  436. continue;
  437. }
  438. t = grub_strtoul (ptr, &ptr, 16);
  439. if (grub_errno)
  440. {
  441. grub_errno = GRUB_ERR_NONE;
  442. break;
  443. }
  444. if (t & ~0xffff)
  445. return 0;
  446. newip[word] = grub_cpu_to_be16 (t);
  447. if (*ptr != ':')
  448. break;
  449. ptr++;
  450. }
  451. if (quaddot == -1 && word < 7)
  452. return 0;
  453. if (quaddot != -1)
  454. {
  455. grub_memmove (&newip[quaddot + 7 - word], &newip[quaddot],
  456. (word - quaddot + 1) * sizeof (newip[0]));
  457. grub_memset (&newip[quaddot], 0, (7 - word) * sizeof (newip[0]));
  458. }
  459. grub_memcpy (ip, newip, 16);
  460. if (bracketed && *ptr == ']')
  461. ptr++;
  462. if (rest)
  463. *rest = ptr;
  464. return 1;
  465. }
  466. static int
  467. match_net (const grub_net_network_level_netaddress_t *net,
  468. const grub_net_network_level_address_t *addr)
  469. {
  470. if (net->type != addr->type)
  471. return 0;
  472. switch (net->type)
  473. {
  474. case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV:
  475. return 0;
  476. case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4:
  477. {
  478. grub_uint32_t mask = (0xffffffffU << (32 - net->ipv4.masksize));
  479. if (net->ipv4.masksize == 0)
  480. mask = 0;
  481. return ((grub_be_to_cpu32 (net->ipv4.base) & mask)
  482. == (grub_be_to_cpu32 (addr->ipv4) & mask));
  483. }
  484. case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6:
  485. {
  486. grub_uint64_t mask[2];
  487. if (net->ipv6.masksize == 0)
  488. return 1;
  489. if (net->ipv6.masksize <= 64)
  490. {
  491. mask[0] = 0xffffffffffffffffULL << (64 - net->ipv6.masksize);
  492. mask[1] = 0;
  493. }
  494. else
  495. {
  496. mask[0] = 0xffffffffffffffffULL;
  497. mask[1] = 0xffffffffffffffffULL << (128 - net->ipv6.masksize);
  498. }
  499. return (((grub_be_to_cpu64 (net->ipv6.base[0]) & mask[0])
  500. == (grub_be_to_cpu64 (addr->ipv6[0]) & mask[0]))
  501. && ((grub_be_to_cpu64 (net->ipv6.base[1]) & mask[1])
  502. == (grub_be_to_cpu64 (addr->ipv6[1]) & mask[1])));
  503. }
  504. }
  505. return 0;
  506. }
  507. grub_err_t
  508. grub_net_resolve_address (const char *name,
  509. grub_net_network_level_address_t *addr)
  510. {
  511. const char *rest;
  512. grub_err_t err;
  513. grub_size_t naddresses;
  514. struct grub_net_network_level_address *addresses = 0;
  515. if (parse_ip (name, &addr->ipv4, &rest) && *rest == 0)
  516. {
  517. addr->type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
  518. return GRUB_ERR_NONE;
  519. }
  520. if (parse_ip6 (name, addr->ipv6, &rest) && *rest == 0)
  521. {
  522. addr->type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
  523. return GRUB_ERR_NONE;
  524. }
  525. err = grub_net_dns_lookup (name, 0, 0, &naddresses, &addresses, 1);
  526. if (err)
  527. return err;
  528. if (!naddresses)
  529. grub_error (GRUB_ERR_NET_BAD_ADDRESS, N_("unresolvable address %s"),
  530. name);
  531. /* FIXME: use other results as well. */
  532. *addr = addresses[0];
  533. grub_free (addresses);
  534. return GRUB_ERR_NONE;
  535. }
  536. grub_err_t
  537. grub_net_resolve_net_address (const char *name,
  538. grub_net_network_level_netaddress_t *addr)
  539. {
  540. const char *rest;
  541. if (parse_ip (name, &addr->ipv4.base, &rest))
  542. {
  543. addr->type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
  544. if (*rest == '/')
  545. {
  546. addr->ipv4.masksize = grub_strtoul (rest + 1, &rest, 0);
  547. if (!grub_errno && *rest == 0)
  548. return GRUB_ERR_NONE;
  549. grub_errno = GRUB_ERR_NONE;
  550. }
  551. else if (*rest == 0)
  552. {
  553. addr->ipv4.masksize = 32;
  554. return GRUB_ERR_NONE;
  555. }
  556. }
  557. if (parse_ip6 (name, addr->ipv6.base, &rest))
  558. {
  559. addr->type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
  560. if (*rest == '/')
  561. {
  562. addr->ipv6.masksize = grub_strtoul (rest + 1, &rest, 0);
  563. if (!grub_errno && *rest == 0)
  564. return GRUB_ERR_NONE;
  565. grub_errno = GRUB_ERR_NONE;
  566. }
  567. else if (*rest == 0)
  568. {
  569. addr->ipv6.masksize = 128;
  570. return GRUB_ERR_NONE;
  571. }
  572. }
  573. return grub_error (GRUB_ERR_NET_BAD_ADDRESS,
  574. N_("unrecognised network address `%s'"),
  575. name);
  576. }
  577. static int
  578. route_cmp (const struct grub_net_route *a, const struct grub_net_route *b)
  579. {
  580. if (a == NULL && b == NULL)
  581. return 0;
  582. if (b == NULL)
  583. return +1;
  584. if (a == NULL)
  585. return -1;
  586. if (a->target.type < b->target.type)
  587. return -1;
  588. if (a->target.type > b->target.type)
  589. return +1;
  590. switch (a->target.type)
  591. {
  592. case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV:
  593. break;
  594. case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6:
  595. if (a->target.ipv6.masksize > b->target.ipv6.masksize)
  596. return +1;
  597. if (a->target.ipv6.masksize < b->target.ipv6.masksize)
  598. return -1;
  599. break;
  600. case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4:
  601. if (a->target.ipv4.masksize > b->target.ipv4.masksize)
  602. return +1;
  603. if (a->target.ipv4.masksize < b->target.ipv4.masksize)
  604. return -1;
  605. break;
  606. }
  607. return 0;
  608. }
  609. grub_err_t
  610. grub_net_route_address (grub_net_network_level_address_t addr,
  611. grub_net_network_level_address_t *gateway,
  612. struct grub_net_network_level_interface **interf)
  613. {
  614. struct grub_net_route *route;
  615. unsigned int depth = 0;
  616. unsigned int routecnt = 0;
  617. struct grub_net_network_level_protocol *prot = NULL;
  618. grub_net_network_level_address_t curtarget = addr;
  619. *gateway = addr;
  620. FOR_NET_ROUTES(route)
  621. routecnt++;
  622. for (depth = 0; depth < routecnt + 2 && depth < GRUB_UINT_MAX; depth++)
  623. {
  624. struct grub_net_route *bestroute = NULL;
  625. FOR_NET_ROUTES(route)
  626. {
  627. if (depth && prot != route->prot)
  628. continue;
  629. if (!match_net (&route->target, &curtarget))
  630. continue;
  631. if (route_cmp (route, bestroute) > 0)
  632. bestroute = route;
  633. }
  634. if (bestroute == NULL)
  635. return grub_error (GRUB_ERR_NET_NO_ROUTE,
  636. N_("destination unreachable"));
  637. if (!bestroute->is_gateway)
  638. {
  639. *interf = bestroute->interface;
  640. return GRUB_ERR_NONE;
  641. }
  642. if (depth == 0)
  643. {
  644. *gateway = bestroute->gw;
  645. if (bestroute->interface != NULL)
  646. {
  647. *interf = bestroute->interface;
  648. return GRUB_ERR_NONE;
  649. }
  650. }
  651. curtarget = bestroute->gw;
  652. }
  653. return grub_error (GRUB_ERR_NET_ROUTE_LOOP,
  654. /* TRANSLATORS: route loop is a condition when e.g.
  655. to contact server A you need to go through B
  656. and to contact B you need to go through A. */
  657. N_("route loop detected"));
  658. }
  659. static grub_err_t
  660. grub_cmd_deladdr (struct grub_command *cmd __attribute__ ((unused)),
  661. int argc, char **args)
  662. {
  663. struct grub_net_network_level_interface *inter;
  664. if (argc != 1)
  665. return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
  666. FOR_NET_NETWORK_LEVEL_INTERFACES (inter)
  667. if (grub_strcmp (inter->name, args[0]) == 0)
  668. break;
  669. if (inter == NULL)
  670. return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("address not found"));
  671. if (inter->flags & GRUB_NET_INTERFACE_PERMANENT)
  672. return grub_error (GRUB_ERR_IO,
  673. N_("you can't delete this address"));
  674. grub_net_network_level_interface_unregister (inter);
  675. grub_free (inter->name);
  676. grub_free (inter);
  677. return GRUB_ERR_NONE;
  678. }
  679. void
  680. grub_net_addr_to_str (const grub_net_network_level_address_t *target, char *buf)
  681. {
  682. switch (target->type)
  683. {
  684. case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV:
  685. COMPILE_TIME_ASSERT (sizeof ("temporary") < GRUB_NET_MAX_STR_ADDR_LEN);
  686. grub_strcpy (buf, "temporary");
  687. return;
  688. case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6:
  689. {
  690. char *ptr = buf;
  691. grub_uint64_t n = grub_be_to_cpu64 (target->ipv6[0]);
  692. int i;
  693. for (i = 0; i < 4; i++)
  694. {
  695. grub_snprintf (ptr, 6, "%" PRIxGRUB_UINT64_T ":",
  696. (n >> (48 - 16 * i)) & 0xffff);
  697. ptr += grub_strlen (ptr);
  698. }
  699. n = grub_be_to_cpu64 (target->ipv6[1]);
  700. for (i = 0; i < 3; i++)
  701. {
  702. grub_snprintf (ptr, 6, "%" PRIxGRUB_UINT64_T ":",
  703. (n >> (48 - 16 * i)) & 0xffff);
  704. ptr += grub_strlen (ptr);
  705. }
  706. grub_snprintf (ptr, 5, "%" PRIxGRUB_UINT64_T, n & 0xffff);
  707. return;
  708. }
  709. case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4:
  710. {
  711. grub_uint32_t n = grub_be_to_cpu32 (target->ipv4);
  712. grub_snprintf (buf, GRUB_NET_MAX_STR_ADDR_LEN, "%d.%d.%d.%d",
  713. ((n >> 24) & 0xff), ((n >> 16) & 0xff),
  714. ((n >> 8) & 0xff), ((n >> 0) & 0xff));
  715. }
  716. return;
  717. }
  718. grub_snprintf (buf, GRUB_NET_MAX_STR_ADDR_LEN,
  719. "Unknown address type %d", target->type);
  720. }
  721. void
  722. grub_net_hwaddr_to_str (const grub_net_link_level_address_t *addr, char *str)
  723. {
  724. str[0] = 0;
  725. switch (addr->type)
  726. {
  727. case GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET:
  728. {
  729. char *ptr;
  730. unsigned i;
  731. for (ptr = str, i = 0; i < ARRAY_SIZE (addr->mac); i++)
  732. {
  733. grub_snprintf (ptr, GRUB_NET_MAX_STR_HWADDR_LEN - (ptr - str),
  734. "%02x:", addr->mac[i] & 0xff);
  735. ptr += (sizeof ("XX:") - 1);
  736. }
  737. return;
  738. }
  739. }
  740. grub_printf (_("Unsupported hw address type %d\n"), addr->type);
  741. }
  742. void
  743. grub_net_vlan_to_str (grub_uint16_t vlantag, char *str)
  744. {
  745. str[0] = 0;
  746. /* 12 bits are used to identify the vlan in 802.1Q. */
  747. vlantag = vlantag & 0x0fff;
  748. if (vlantag == 0)
  749. return;
  750. grub_snprintf (str, GRUB_NET_MAX_STR_VLAN_LEN, "vlan%u", vlantag);
  751. }
  752. int
  753. grub_net_hwaddr_cmp (const grub_net_link_level_address_t *a,
  754. const grub_net_link_level_address_t *b)
  755. {
  756. if (a->type < b->type)
  757. return -1;
  758. if (a->type > b->type)
  759. return +1;
  760. switch (a->type)
  761. {
  762. case GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET:
  763. return grub_memcmp (a->mac, b->mac, sizeof (a->mac));
  764. }
  765. grub_printf (_("Unsupported hw address type %d\n"), a->type);
  766. return 1;
  767. }
  768. int
  769. grub_net_addr_cmp (const grub_net_network_level_address_t *a,
  770. const grub_net_network_level_address_t *b)
  771. {
  772. if (a->type < b->type)
  773. return -1;
  774. if (a->type > b->type)
  775. return +1;
  776. switch (a->type)
  777. {
  778. case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4:
  779. return grub_memcmp (&a->ipv4, &b->ipv4, sizeof (a->ipv4));
  780. case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6:
  781. return grub_memcmp (&a->ipv6, &b->ipv6, sizeof (a->ipv6));
  782. case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV:
  783. return 0;
  784. }
  785. grub_printf (_("Unsupported address type %d\n"), a->type);
  786. return 1;
  787. }
  788. /* FIXME: implement this. */
  789. static char *
  790. hwaddr_set_env (struct grub_env_var *var __attribute__ ((unused)),
  791. const char *val __attribute__ ((unused)))
  792. {
  793. return NULL;
  794. }
  795. /* FIXME: implement this. */
  796. static char *
  797. addr_set_env (struct grub_env_var *var __attribute__ ((unused)),
  798. const char *val __attribute__ ((unused)))
  799. {
  800. return NULL;
  801. }
  802. static char *
  803. defserver_set_env (struct grub_env_var *var __attribute__ ((unused)),
  804. const char *val)
  805. {
  806. grub_free (grub_net_default_server);
  807. grub_net_default_server = grub_strdup (val);
  808. return grub_strdup (val);
  809. }
  810. static const char *
  811. defserver_get_env (struct grub_env_var *var __attribute__ ((unused)),
  812. const char *val __attribute__ ((unused)))
  813. {
  814. return grub_net_default_server ? : "";
  815. }
  816. static const char *
  817. defip_get_env (struct grub_env_var *var __attribute__ ((unused)),
  818. const char *val __attribute__ ((unused)))
  819. {
  820. const char *intf = grub_env_get ("net_default_interface");
  821. const char *ret = NULL;
  822. if (intf)
  823. {
  824. char *buf = grub_xasprintf ("net_%s_ip", intf);
  825. if (buf)
  826. ret = grub_env_get (buf);
  827. grub_free (buf);
  828. }
  829. return ret;
  830. }
  831. static char *
  832. defip_set_env (struct grub_env_var *var __attribute__ ((unused)),
  833. const char *val)
  834. {
  835. const char *intf = grub_env_get ("net_default_interface");
  836. if (intf)
  837. {
  838. char *buf = grub_xasprintf ("net_%s_ip", intf);
  839. if (buf)
  840. grub_env_set (buf, val);
  841. grub_free (buf);
  842. }
  843. return NULL;
  844. }
  845. static const char *
  846. defmac_get_env (struct grub_env_var *var __attribute__ ((unused)),
  847. const char *val __attribute__ ((unused)))
  848. {
  849. const char *intf = grub_env_get ("net_default_interface");
  850. const char *ret = NULL;
  851. if (intf)
  852. {
  853. char *buf = grub_xasprintf ("net_%s_mac", intf);
  854. if (buf)
  855. ret = grub_env_get (buf);
  856. grub_free (buf);
  857. }
  858. return ret;
  859. }
  860. static char *
  861. defmac_set_env (struct grub_env_var *var __attribute__ ((unused)),
  862. const char *val)
  863. {
  864. const char *intf = grub_env_get ("net_default_interface");
  865. if (intf)
  866. {
  867. char *buf = grub_xasprintf ("net_%s_mac", intf);
  868. if (buf)
  869. grub_env_set (buf, val);
  870. grub_free (buf);
  871. }
  872. return NULL;
  873. }
  874. static void
  875. grub_net_network_level_interface_register (struct grub_net_network_level_interface *inter)
  876. {
  877. {
  878. char buf[GRUB_NET_MAX_STR_HWADDR_LEN];
  879. char *name;
  880. char *ptr;
  881. grub_net_hwaddr_to_str (&inter->hwaddress, buf);
  882. name = grub_xasprintf ("net_%s_mac", inter->name);
  883. if (!name)
  884. return;
  885. for (ptr = name; *ptr; ptr++)
  886. if (*ptr == ':')
  887. *ptr = '_';
  888. grub_env_set (name, buf);
  889. grub_register_variable_hook (name, 0, hwaddr_set_env);
  890. grub_env_export (name);
  891. grub_free (name);
  892. }
  893. {
  894. char buf[GRUB_NET_MAX_STR_ADDR_LEN];
  895. char *name;
  896. char *ptr;
  897. grub_net_addr_to_str (&inter->address, buf);
  898. name = grub_xasprintf ("net_%s_ip", inter->name);
  899. if (!name)
  900. return;
  901. for (ptr = name; *ptr; ptr++)
  902. if (*ptr == ':')
  903. *ptr = '_';
  904. grub_env_set (name, buf);
  905. grub_register_variable_hook (name, 0, addr_set_env);
  906. grub_env_export (name);
  907. grub_free (name);
  908. }
  909. inter->card->num_ifaces++;
  910. inter->prev = &grub_net_network_level_interfaces;
  911. inter->next = grub_net_network_level_interfaces;
  912. if (inter->next)
  913. inter->next->prev = &inter->next;
  914. grub_net_network_level_interfaces = inter;
  915. }
  916. void
  917. grub_net_network_level_interface_unregister (struct grub_net_network_level_interface *inter)
  918. {
  919. char *name;
  920. {
  921. char buf[GRUB_NET_MAX_STR_HWADDR_LEN];
  922. grub_net_hwaddr_to_str (&inter->hwaddress, buf);
  923. name = grub_xasprintf ("net_%s_mac", inter->name);
  924. if (name != NULL)
  925. grub_register_variable_hook (name, NULL, NULL);
  926. grub_free (name);
  927. }
  928. {
  929. char buf[GRUB_NET_MAX_STR_ADDR_LEN];
  930. grub_net_addr_to_str (&inter->address, buf);
  931. name = grub_xasprintf ("net_%s_ip", inter->name);
  932. if (name != NULL)
  933. grub_register_variable_hook (name, NULL, NULL);
  934. grub_free (name);
  935. }
  936. inter->card->num_ifaces--;
  937. *inter->prev = inter->next;
  938. if (inter->next)
  939. inter->next->prev = inter->prev;
  940. inter->next = 0;
  941. inter->prev = 0;
  942. }
  943. grub_err_t
  944. grub_net_add_ipv4_local (struct grub_net_network_level_interface *inter,
  945. int mask)
  946. {
  947. grub_uint32_t ip_cpu;
  948. struct grub_net_route *route;
  949. if (inter->address.type != GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4)
  950. return 0;
  951. ip_cpu = grub_be_to_cpu32 (inter->address.ipv4);
  952. if (mask == -1)
  953. {
  954. if (!(ip_cpu & 0x80000000))
  955. mask = 8;
  956. else if (!(ip_cpu & 0x40000000))
  957. mask = 16;
  958. else if (!(ip_cpu & 0x20000000))
  959. mask = 24;
  960. }
  961. if (mask == -1)
  962. return 0;
  963. route = grub_zalloc (sizeof (*route));
  964. if (!route)
  965. return grub_errno;
  966. route->name = grub_xasprintf ("%s:local", inter->name);
  967. if (!route->name)
  968. {
  969. grub_free (route);
  970. return grub_errno;
  971. }
  972. route->target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
  973. route->target.ipv4.base = grub_cpu_to_be32 (ip_cpu & (0xffffffff << (32 - mask)));
  974. route->target.ipv4.masksize = mask;
  975. route->is_gateway = 0;
  976. route->interface = inter;
  977. grub_net_route_register (route);
  978. return 0;
  979. }
  980. /* FIXME: support MAC specifying. */
  981. static grub_err_t
  982. grub_cmd_addaddr (struct grub_command *cmd __attribute__ ((unused)),
  983. int argc, char **args)
  984. {
  985. struct grub_net_card *card;
  986. grub_net_network_level_address_t addr;
  987. grub_err_t err;
  988. grub_net_interface_flags_t flags = 0;
  989. struct grub_net_network_level_interface *inf;
  990. if (argc != 3)
  991. return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("three arguments expected"));
  992. FOR_NET_CARDS (card)
  993. if (grub_strcmp (card->name, args[1]) == 0)
  994. break;
  995. if (card == NULL)
  996. return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("card not found"));
  997. err = grub_net_resolve_address (args[2], &addr);
  998. if (err)
  999. return err;
  1000. if (card->flags & GRUB_NET_CARD_NO_MANUAL_INTERFACES)
  1001. return grub_error (GRUB_ERR_IO,
  1002. "this card doesn't support address addition");
  1003. if (card->flags & GRUB_NET_CARD_HWADDRESS_IMMUTABLE)
  1004. flags |= GRUB_NET_INTERFACE_HWADDRESS_IMMUTABLE;
  1005. inf = grub_net_add_addr (args[0], card, &addr, &card->default_address,
  1006. flags);
  1007. if (inf)
  1008. grub_net_add_ipv4_local (inf, -1);
  1009. return grub_errno;
  1010. }
  1011. static grub_err_t
  1012. grub_cmd_delroute (struct grub_command *cmd __attribute__ ((unused)),
  1013. int argc, char **args)
  1014. {
  1015. struct grub_net_route *route;
  1016. struct grub_net_route **prev;
  1017. if (argc != 1)
  1018. return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
  1019. for (prev = &grub_net_routes, route = *prev; route; prev = &((*prev)->next),
  1020. route = *prev)
  1021. if (grub_strcmp (route->name, args[0]) == 0)
  1022. {
  1023. *prev = route->next;
  1024. grub_free (route->name);
  1025. grub_free (route);
  1026. if (!*prev)
  1027. break;
  1028. }
  1029. return GRUB_ERR_NONE;
  1030. }
  1031. grub_err_t
  1032. grub_net_add_route (const char *name,
  1033. grub_net_network_level_netaddress_t target,
  1034. struct grub_net_network_level_interface *inter)
  1035. {
  1036. struct grub_net_route *route;
  1037. route = grub_zalloc (sizeof (*route));
  1038. if (!route)
  1039. return grub_errno;
  1040. route->name = grub_strdup (name);
  1041. if (!route->name)
  1042. {
  1043. grub_free (route);
  1044. return grub_errno;
  1045. }
  1046. route->target = target;
  1047. route->is_gateway = 0;
  1048. route->interface = inter;
  1049. grub_net_route_register (route);
  1050. return GRUB_ERR_NONE;
  1051. }
  1052. grub_err_t
  1053. grub_net_add_route_gw (const char *name,
  1054. grub_net_network_level_netaddress_t target,
  1055. grub_net_network_level_address_t gw,
  1056. struct grub_net_network_level_interface *inter)
  1057. {
  1058. struct grub_net_route *route;
  1059. route = grub_zalloc (sizeof (*route));
  1060. if (!route)
  1061. return grub_errno;
  1062. route->name = grub_strdup (name);
  1063. if (!route->name)
  1064. {
  1065. grub_free (route);
  1066. return grub_errno;
  1067. }
  1068. route->target = target;
  1069. route->is_gateway = 1;
  1070. route->gw = gw;
  1071. route->interface = inter;
  1072. grub_net_route_register (route);
  1073. return GRUB_ERR_NONE;
  1074. }
  1075. static grub_err_t
  1076. grub_cmd_addroute (struct grub_command *cmd __attribute__ ((unused)),
  1077. int argc, char **args)
  1078. {
  1079. grub_net_network_level_netaddress_t target;
  1080. if (argc < 3)
  1081. return grub_error (GRUB_ERR_BAD_ARGUMENT,
  1082. N_("three arguments expected"));
  1083. grub_net_resolve_net_address (args[1], &target);
  1084. if (grub_strcmp (args[2], "gw") == 0 && argc >= 4)
  1085. {
  1086. grub_err_t err;
  1087. grub_net_network_level_address_t gw;
  1088. err = grub_net_resolve_address (args[3], &gw);
  1089. if (err)
  1090. return err;
  1091. return grub_net_add_route_gw (args[0], target, gw, NULL);
  1092. }
  1093. else
  1094. {
  1095. struct grub_net_network_level_interface *inter;
  1096. FOR_NET_NETWORK_LEVEL_INTERFACES (inter)
  1097. if (grub_strcmp (inter->name, args[2]) == 0)
  1098. break;
  1099. if (!inter)
  1100. return grub_error (GRUB_ERR_BAD_ARGUMENT,
  1101. N_("unrecognised network interface `%s'"), args[2]);
  1102. return grub_net_add_route (args[0], target, inter);
  1103. }
  1104. }
  1105. static grub_err_t
  1106. grub_cmd_setvlan (struct grub_command *cmd __attribute__ ((unused)),
  1107. int argc, char **args)
  1108. {
  1109. const char *vlan_string, *vlan_string_end;
  1110. unsigned long vlantag;
  1111. struct grub_net_network_level_interface *inter;
  1112. if (argc != 2)
  1113. return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected"));
  1114. vlan_string = args[1];
  1115. vlantag = grub_strtoul (vlan_string, &vlan_string_end, 10);
  1116. if (*vlan_string == '\0' || *vlan_string_end != '\0')
  1117. return grub_error (GRUB_ERR_BAD_NUMBER,
  1118. N_("non-numeric or invalid number `%s'"), vlan_string);
  1119. if (vlantag > 4094)
  1120. return grub_error (GRUB_ERR_OUT_OF_RANGE,
  1121. N_("vlan id `%s' not in the valid range of 0-4094"),
  1122. vlan_string);
  1123. FOR_NET_NETWORK_LEVEL_INTERFACES (inter)
  1124. {
  1125. if (grub_strcmp (inter->name, args[0]) != 0)
  1126. continue;
  1127. inter->vlantag = vlantag;
  1128. return GRUB_ERR_NONE;
  1129. }
  1130. return grub_error (GRUB_ERR_BAD_ARGUMENT,
  1131. N_("network interface not found"));
  1132. }
  1133. static void
  1134. print_net_address (const grub_net_network_level_netaddress_t *target)
  1135. {
  1136. switch (target->type)
  1137. {
  1138. case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV:
  1139. /* TRANSLATORS: it refers to the network address. */
  1140. grub_printf ("%s\n", _("temporary"));
  1141. return;
  1142. case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4:
  1143. {
  1144. grub_uint32_t n = grub_be_to_cpu32 (target->ipv4.base);
  1145. grub_printf ("%d.%d.%d.%d/%d ", ((n >> 24) & 0xff),
  1146. ((n >> 16) & 0xff),
  1147. ((n >> 8) & 0xff),
  1148. ((n >> 0) & 0xff),
  1149. target->ipv4.masksize);
  1150. }
  1151. return;
  1152. case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6:
  1153. {
  1154. char buf[GRUB_NET_MAX_STR_ADDR_LEN];
  1155. struct grub_net_network_level_address base;
  1156. base.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
  1157. grub_memcpy (&base.ipv6, &target->ipv6, 16);
  1158. grub_net_addr_to_str (&base, buf);
  1159. grub_printf ("%s/%d ", buf, target->ipv6.masksize);
  1160. }
  1161. return;
  1162. }
  1163. grub_printf (_("Unknown address type %d\n"), target->type);
  1164. }
  1165. static void
  1166. print_address (const grub_net_network_level_address_t *target)
  1167. {
  1168. char buf[GRUB_NET_MAX_STR_ADDR_LEN];
  1169. grub_net_addr_to_str (target, buf);
  1170. grub_xputs (buf);
  1171. }
  1172. static grub_err_t
  1173. grub_cmd_listroutes (struct grub_command *cmd __attribute__ ((unused)),
  1174. int argc __attribute__ ((unused)),
  1175. char **args __attribute__ ((unused)))
  1176. {
  1177. struct grub_net_route *route;
  1178. FOR_NET_ROUTES(route)
  1179. {
  1180. grub_printf ("%s ", route->name);
  1181. print_net_address (&route->target);
  1182. if (route->is_gateway)
  1183. {
  1184. grub_printf ("gw ");
  1185. print_address (&route->gw);
  1186. }
  1187. else
  1188. grub_printf ("%s", route->interface->name);
  1189. grub_printf ("\n");
  1190. }
  1191. return GRUB_ERR_NONE;
  1192. }
  1193. static grub_err_t
  1194. grub_cmd_listcards (struct grub_command *cmd __attribute__ ((unused)),
  1195. int argc __attribute__ ((unused)),
  1196. char **args __attribute__ ((unused)))
  1197. {
  1198. struct grub_net_card *card;
  1199. FOR_NET_CARDS(card)
  1200. {
  1201. char buf[GRUB_NET_MAX_STR_HWADDR_LEN];
  1202. grub_net_hwaddr_to_str (&card->default_address, buf);
  1203. grub_printf ("%s %s\n", card->name, buf);
  1204. }
  1205. return GRUB_ERR_NONE;
  1206. }
  1207. static grub_err_t
  1208. grub_cmd_listaddrs (struct grub_command *cmd __attribute__ ((unused)),
  1209. int argc __attribute__ ((unused)),
  1210. char **args __attribute__ ((unused)))
  1211. {
  1212. struct grub_net_network_level_interface *inf;
  1213. FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
  1214. {
  1215. char bufh[GRUB_NET_MAX_STR_HWADDR_LEN];
  1216. char bufn[GRUB_NET_MAX_STR_ADDR_LEN];
  1217. char bufv[GRUB_NET_MAX_STR_VLAN_LEN];
  1218. grub_net_hwaddr_to_str (&inf->hwaddress, bufh);
  1219. grub_net_addr_to_str (&inf->address, bufn);
  1220. grub_net_vlan_to_str (inf->vlantag, bufv);
  1221. grub_printf ("%s %s %s %s\n", inf->name, bufh, bufn, bufv);
  1222. }
  1223. return GRUB_ERR_NONE;
  1224. }
  1225. grub_net_app_level_t grub_net_app_level_list;
  1226. struct grub_net_socket *grub_net_sockets;
  1227. static grub_net_t
  1228. grub_net_open_real (const char *name)
  1229. {
  1230. grub_net_app_level_t proto;
  1231. const char *protname, *server;
  1232. char *host, *port_start;
  1233. grub_size_t protnamelen;
  1234. int try;
  1235. int port = 0;
  1236. if (grub_strncmp (name, "pxe:", sizeof ("pxe:") - 1) == 0)
  1237. {
  1238. protname = "tftp";
  1239. protnamelen = sizeof ("tftp") - 1;
  1240. server = name + sizeof ("pxe:") - 1;
  1241. }
  1242. else if (grub_strcmp (name, "pxe") == 0)
  1243. {
  1244. protname = "tftp";
  1245. protnamelen = sizeof ("tftp") - 1;
  1246. server = grub_net_default_server;
  1247. }
  1248. else
  1249. {
  1250. const char *comma;
  1251. comma = grub_strchr (name, ',');
  1252. if (comma)
  1253. {
  1254. protnamelen = comma - name;
  1255. server = comma + 1;
  1256. protname = name;
  1257. }
  1258. else
  1259. {
  1260. protnamelen = grub_strlen (name);
  1261. server = grub_net_default_server;
  1262. protname = name;
  1263. }
  1264. }
  1265. if (!server)
  1266. {
  1267. grub_error (GRUB_ERR_NET_BAD_ADDRESS,
  1268. N_("no server is specified"));
  1269. return NULL;
  1270. }
  1271. /* IPv6 or port specified? */
  1272. if ((port_start = grub_strchr (server, ':')))
  1273. {
  1274. char *ipv6_begin;
  1275. if ((ipv6_begin = grub_strchr (server, '[')))
  1276. {
  1277. char *ipv6_end = grub_strchr (server, ']');
  1278. if (!ipv6_end)
  1279. {
  1280. grub_error (GRUB_ERR_NET_BAD_ADDRESS, N_("mismatched [ in address"));
  1281. return NULL;
  1282. }
  1283. /* Port number after bracketed IPv6 addr. */
  1284. if (ipv6_end[1] == ':')
  1285. {
  1286. port = grub_strtoul (ipv6_end + 2, NULL, 10);
  1287. if (port == 0 || port > 65535)
  1288. {
  1289. grub_error (GRUB_ERR_NET_BAD_ADDRESS, N_("bad port number"));
  1290. return NULL;
  1291. }
  1292. }
  1293. host = grub_strndup (ipv6_begin, (ipv6_end - ipv6_begin) + 1);
  1294. }
  1295. else
  1296. {
  1297. if (grub_strchr (port_start + 1, ':'))
  1298. {
  1299. int iplen = grub_strlen (server);
  1300. grub_size_t sz;
  1301. /* Bracket bare IPv6 addr. */
  1302. if (grub_add (iplen, 3, &sz))
  1303. {
  1304. grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow detected while obtaining length of host"));
  1305. return NULL;
  1306. }
  1307. host = grub_malloc (sz);
  1308. if (!host)
  1309. return NULL;
  1310. host[0] = '[';
  1311. grub_memcpy (host + 1, server, iplen);
  1312. host[iplen + 1] = ']';
  1313. host[iplen + 2] = '\0';
  1314. }
  1315. else
  1316. {
  1317. /* hostname:port or IPv4:port */
  1318. port = grub_strtol (port_start + 1, NULL, 10);
  1319. if (port == 0 || port > 65535)
  1320. {
  1321. grub_error (GRUB_ERR_NET_BAD_ADDRESS, N_("bad port number"));
  1322. return NULL;
  1323. }
  1324. host = grub_strndup (server, port_start - server);
  1325. }
  1326. }
  1327. }
  1328. else
  1329. host = grub_strdup (server);
  1330. if (!host)
  1331. return NULL;
  1332. for (try = 0; try < 2; try++)
  1333. {
  1334. FOR_NET_APP_LEVEL (proto)
  1335. {
  1336. if (grub_memcmp (proto->name, protname, protnamelen) == 0
  1337. && proto->name[protnamelen] == 0)
  1338. {
  1339. grub_net_t ret = grub_zalloc (sizeof (*ret));
  1340. if (!ret)
  1341. {
  1342. grub_free (host);
  1343. return NULL;
  1344. }
  1345. ret->protocol = proto;
  1346. ret->port = port;
  1347. ret->server = host;
  1348. ret->fs = &grub_net_fs;
  1349. return ret;
  1350. }
  1351. }
  1352. if (try == 0)
  1353. {
  1354. const char *prefix, *root;
  1355. char *prefdev, *comma;
  1356. int skip = 0;
  1357. grub_size_t devlen;
  1358. /* Do not attempt to load module if it requires protocol provided
  1359. by this module - it results in infinite recursion. Just continue,
  1360. fail and cleanup on next iteration.
  1361. */
  1362. prefix = grub_env_get ("prefix");
  1363. if (!prefix)
  1364. continue;
  1365. prefdev = grub_file_get_device_name (prefix);
  1366. if (!prefdev)
  1367. {
  1368. root = grub_env_get ("root");
  1369. if (!root)
  1370. continue;
  1371. prefdev = grub_strdup (root);
  1372. if (!prefdev)
  1373. continue;
  1374. }
  1375. if (grub_strncmp (prefdev, "pxe", sizeof ("pxe") - 1) == 0 &&
  1376. (!prefdev[sizeof ("pxe") - 1] || (prefdev[sizeof("pxe") - 1] == ':')))
  1377. {
  1378. grub_free (prefdev);
  1379. prefdev = grub_strdup ("tftp");
  1380. if (!prefdev)
  1381. continue;
  1382. }
  1383. comma = grub_strchr (prefdev, ',');
  1384. if (comma)
  1385. *comma = '\0';
  1386. devlen = grub_strlen (prefdev);
  1387. if (protnamelen == devlen && grub_memcmp (prefdev, protname, devlen) == 0)
  1388. skip = 1;
  1389. grub_free (prefdev);
  1390. if (skip)
  1391. continue;
  1392. if (sizeof ("http") - 1 == protnamelen
  1393. && grub_memcmp ("http", protname, protnamelen) == 0)
  1394. {
  1395. grub_dl_load ("http");
  1396. grub_errno = GRUB_ERR_NONE;
  1397. continue;
  1398. }
  1399. if (sizeof ("tftp") - 1 == protnamelen
  1400. && grub_memcmp ("tftp", protname, protnamelen) == 0)
  1401. {
  1402. grub_dl_load ("tftp");
  1403. grub_errno = GRUB_ERR_NONE;
  1404. continue;
  1405. }
  1406. }
  1407. break;
  1408. }
  1409. /* Restore original error. */
  1410. grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("disk `%s' not found"),
  1411. name);
  1412. grub_free (host);
  1413. return NULL;
  1414. }
  1415. static grub_err_t
  1416. grub_net_fs_dir (grub_device_t device, const char *path __attribute__ ((unused)),
  1417. grub_fs_dir_hook_t hook __attribute__ ((unused)),
  1418. void *hook_data __attribute__ ((unused)))
  1419. {
  1420. if (!device->net)
  1421. return grub_error (GRUB_ERR_BUG, "invalid net device");
  1422. return GRUB_ERR_NONE;
  1423. }
  1424. static grub_err_t
  1425. grub_net_fs_open (struct grub_file *file_out, const char *name)
  1426. {
  1427. grub_err_t err;
  1428. struct grub_file *file, *bufio;
  1429. file = grub_malloc (sizeof (*file));
  1430. if (!file)
  1431. return grub_errno;
  1432. grub_memcpy (file, file_out, sizeof (struct grub_file));
  1433. file->device->net->packs.first = NULL;
  1434. file->device->net->packs.last = NULL;
  1435. file->device->net->name = grub_strdup (name);
  1436. if (!file->device->net->name)
  1437. {
  1438. grub_free (file);
  1439. return grub_errno;
  1440. }
  1441. err = file->device->net->protocol->open (file, name);
  1442. if (err)
  1443. {
  1444. while (file->device->net->packs.first)
  1445. {
  1446. grub_netbuff_free (file->device->net->packs.first->nb);
  1447. grub_net_remove_packet (file->device->net->packs.first);
  1448. }
  1449. grub_free (file->device->net->name);
  1450. grub_free (file);
  1451. return err;
  1452. }
  1453. bufio = grub_bufio_open (file, 32768);
  1454. if (! bufio)
  1455. {
  1456. while (file->device->net->packs.first)
  1457. {
  1458. grub_netbuff_free (file->device->net->packs.first->nb);
  1459. grub_net_remove_packet (file->device->net->packs.first);
  1460. }
  1461. file->device->net->protocol->close (file);
  1462. grub_free (file->device->net->name);
  1463. grub_free (file);
  1464. return grub_errno;
  1465. }
  1466. grub_memcpy (file_out, bufio, sizeof (struct grub_file));
  1467. grub_free (bufio);
  1468. return GRUB_ERR_NONE;
  1469. }
  1470. static grub_err_t
  1471. grub_net_fs_close (grub_file_t file)
  1472. {
  1473. while (file->device->net->packs.first)
  1474. {
  1475. grub_netbuff_free (file->device->net->packs.first->nb);
  1476. grub_net_remove_packet (file->device->net->packs.first);
  1477. }
  1478. if (!file->device->net->broken)
  1479. file->device->net->protocol->close (file);
  1480. grub_free (file->device->net->name);
  1481. return GRUB_ERR_NONE;
  1482. }
  1483. static void
  1484. receive_packets (struct grub_net_card *card, int *stop_condition)
  1485. {
  1486. int received = 0;
  1487. if (card->num_ifaces == 0)
  1488. return;
  1489. if (!card->opened)
  1490. {
  1491. grub_err_t err = GRUB_ERR_NONE;
  1492. if (card->driver->open)
  1493. err = card->driver->open (card);
  1494. if (err)
  1495. {
  1496. grub_errno = GRUB_ERR_NONE;
  1497. return;
  1498. }
  1499. card->opened = 1;
  1500. }
  1501. while (received < 100)
  1502. {
  1503. /* Maybe should be better have a fixed number of packets for each card
  1504. and just mark them as used and not used. */
  1505. struct grub_net_buff *nb;
  1506. if (received > 10 && stop_condition && *stop_condition)
  1507. break;
  1508. nb = card->driver->recv (card);
  1509. if (!nb)
  1510. {
  1511. card->last_poll = grub_get_time_ms ();
  1512. break;
  1513. }
  1514. received++;
  1515. grub_net_recv_ethernet_packet (nb, card);
  1516. if (grub_errno)
  1517. {
  1518. grub_dprintf ("net", "error receiving: %d: %s\n", grub_errno,
  1519. grub_errmsg);
  1520. grub_errno = GRUB_ERR_NONE;
  1521. }
  1522. }
  1523. grub_print_error ();
  1524. }
  1525. static char *
  1526. grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused)),
  1527. const char *val __attribute__ ((unused)))
  1528. {
  1529. return NULL;
  1530. }
  1531. grub_err_t
  1532. grub_env_set_net_property (const char *intername, const char *suffix,
  1533. const char *value, grub_size_t len)
  1534. {
  1535. char *varname, *varvalue;
  1536. char *ptr;
  1537. grub_size_t sz;
  1538. varname = grub_xasprintf ("net_%s_%s", intername, suffix);
  1539. if (!varname)
  1540. return grub_errno;
  1541. for (ptr = varname; *ptr; ptr++)
  1542. if (*ptr == ':')
  1543. *ptr = '_';
  1544. if (grub_add (len, 1, &sz))
  1545. {
  1546. grub_free (varname);
  1547. return grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow detected while obtaining the size of an env variable");
  1548. }
  1549. varvalue = grub_malloc (sz);
  1550. if (!varvalue)
  1551. {
  1552. grub_free (varname);
  1553. return grub_errno;
  1554. }
  1555. grub_memcpy (varvalue, value, len);
  1556. varvalue[len] = 0;
  1557. grub_err_t ret = grub_env_set (varname, varvalue);
  1558. grub_register_variable_hook (varname, 0, grub_env_write_readonly);
  1559. grub_env_export (varname);
  1560. grub_free (varname);
  1561. grub_free (varvalue);
  1562. return ret;
  1563. }
  1564. void
  1565. grub_net_poll_cards (unsigned time, int *stop_condition)
  1566. {
  1567. struct grub_net_card *card;
  1568. grub_uint64_t start_time;
  1569. start_time = grub_get_time_ms ();
  1570. while ((grub_get_time_ms () - start_time) < time
  1571. && (!stop_condition || !*stop_condition))
  1572. FOR_NET_CARDS (card)
  1573. receive_packets (card, stop_condition);
  1574. grub_net_tcp_retransmit ();
  1575. }
  1576. static void
  1577. grub_net_poll_cards_idle_real (void)
  1578. {
  1579. struct grub_net_card *card;
  1580. FOR_NET_CARDS (card)
  1581. {
  1582. grub_uint64_t ctime = grub_get_time_ms ();
  1583. if (ctime < card->last_poll
  1584. || ctime >= card->last_poll + card->idle_poll_delay_ms)
  1585. receive_packets (card, 0);
  1586. }
  1587. if (grub_net_cards != NULL)
  1588. grub_net_tcp_retransmit ();
  1589. }
  1590. /* Read from the packets list*/
  1591. static grub_ssize_t
  1592. grub_net_fs_read_real (grub_file_t file, char *buf, grub_size_t len)
  1593. {
  1594. grub_net_t net = file->device->net;
  1595. struct grub_net_buff *nb;
  1596. char *ptr = buf;
  1597. grub_size_t amount, total = 0;
  1598. int try = 0;
  1599. while (try <= GRUB_NET_TRIES)
  1600. {
  1601. while (net->packs.first)
  1602. {
  1603. try = 0;
  1604. nb = net->packs.first->nb;
  1605. amount = nb->tail - nb->data;
  1606. if (amount > len)
  1607. amount = len;
  1608. len -= amount;
  1609. total += amount;
  1610. file->device->net->offset += amount;
  1611. if (grub_file_progress_hook)
  1612. grub_file_progress_hook (0, 0, amount, NULL, file);
  1613. if (buf)
  1614. {
  1615. grub_memcpy (ptr, nb->data, amount);
  1616. ptr += amount;
  1617. }
  1618. if (amount == (grub_size_t) (nb->tail - nb->data))
  1619. {
  1620. grub_netbuff_free (nb);
  1621. grub_net_remove_packet (net->packs.first);
  1622. }
  1623. else
  1624. nb->data += amount;
  1625. if (!len)
  1626. {
  1627. if (net->protocol->packets_pulled)
  1628. net->protocol->packets_pulled (file);
  1629. return total;
  1630. }
  1631. }
  1632. if (net->protocol->packets_pulled)
  1633. net->protocol->packets_pulled (file);
  1634. if (!net->eof)
  1635. {
  1636. try++;
  1637. grub_net_poll_cards (GRUB_NET_INTERVAL +
  1638. (try * GRUB_NET_INTERVAL_ADDITION), &net->stall);
  1639. }
  1640. else
  1641. return total;
  1642. }
  1643. grub_error (GRUB_ERR_TIMEOUT, N_("timeout reading `%s'"), net->name);
  1644. return -1;
  1645. }
  1646. static grub_off_t
  1647. have_ahead (struct grub_file *file)
  1648. {
  1649. grub_net_t net = file->device->net;
  1650. grub_off_t ret = net->offset;
  1651. struct grub_net_packet *pack;
  1652. for (pack = net->packs.first; pack; pack = pack->next)
  1653. ret += pack->nb->tail - pack->nb->data;
  1654. return ret;
  1655. }
  1656. static grub_err_t
  1657. grub_net_seek_real (struct grub_file *file, grub_off_t offset)
  1658. {
  1659. if (offset == file->device->net->offset)
  1660. return GRUB_ERR_NONE;
  1661. if (offset > file->device->net->offset)
  1662. {
  1663. if (!file->device->net->protocol->seek || have_ahead (file) >= offset)
  1664. {
  1665. grub_net_fs_read_real (file, NULL,
  1666. offset - file->device->net->offset);
  1667. return grub_errno;
  1668. }
  1669. return file->device->net->protocol->seek (file, offset);
  1670. }
  1671. {
  1672. grub_err_t err;
  1673. if (file->device->net->protocol->seek)
  1674. return file->device->net->protocol->seek (file, offset);
  1675. while (file->device->net->packs.first)
  1676. {
  1677. grub_netbuff_free (file->device->net->packs.first->nb);
  1678. grub_net_remove_packet (file->device->net->packs.first);
  1679. }
  1680. file->device->net->protocol->close (file);
  1681. file->device->net->packs.first = NULL;
  1682. file->device->net->packs.last = NULL;
  1683. file->device->net->offset = 0;
  1684. file->device->net->eof = 0;
  1685. file->device->net->stall = 0;
  1686. err = file->device->net->protocol->open (file, file->device->net->name);
  1687. if (err)
  1688. {
  1689. file->device->net->broken = 1;
  1690. return err;
  1691. }
  1692. grub_net_fs_read_real (file, NULL, offset);
  1693. return grub_errno;
  1694. }
  1695. }
  1696. static grub_ssize_t
  1697. grub_net_fs_read (grub_file_t file, char *buf, grub_size_t len)
  1698. {
  1699. if (file->device->net->broken)
  1700. return -1;
  1701. if (file->offset != file->device->net->offset)
  1702. {
  1703. grub_err_t err;
  1704. err = grub_net_seek_real (file, file->offset);
  1705. if (err)
  1706. return err;
  1707. }
  1708. return grub_net_fs_read_real (file, buf, len);
  1709. }
  1710. static struct grub_fs grub_net_fs =
  1711. {
  1712. .name = "netfs",
  1713. .fs_dir = grub_net_fs_dir,
  1714. .fs_open = grub_net_fs_open,
  1715. .fs_read = grub_net_fs_read,
  1716. .fs_close = grub_net_fs_close,
  1717. .fs_label = NULL,
  1718. .fs_uuid = NULL,
  1719. .fs_mtime = NULL,
  1720. };
  1721. static grub_err_t
  1722. grub_net_fini_hw (int noreturn __attribute__ ((unused)))
  1723. {
  1724. struct grub_net_card *card;
  1725. FOR_NET_CARDS (card)
  1726. if (card->opened && !(card->flags & GRUB_NET_CARD_NO_CLOSE_ON_FINI_HW))
  1727. {
  1728. if (card->driver->close)
  1729. card->driver->close (card);
  1730. card->opened = 0;
  1731. }
  1732. return GRUB_ERR_NONE;
  1733. }
  1734. static grub_err_t
  1735. grub_net_restore_hw (void)
  1736. {
  1737. return GRUB_ERR_NONE;
  1738. }
  1739. static int
  1740. grub_config_search_through (char *config, char *suffix,
  1741. grub_size_t num_tries, grub_size_t slice_size)
  1742. {
  1743. while (num_tries-- > 0)
  1744. {
  1745. grub_file_t file;
  1746. grub_dprintf ("net", "attempt to fetch config %s\n", config);
  1747. file = grub_file_open (config, GRUB_FILE_TYPE_CONFIG);
  1748. if (file)
  1749. {
  1750. grub_file_close (file);
  1751. return 0;
  1752. }
  1753. else
  1754. {
  1755. if (grub_errno == GRUB_ERR_IO)
  1756. grub_errno = GRUB_ERR_NONE;
  1757. }
  1758. if (grub_strlen (suffix) < slice_size)
  1759. break;
  1760. config[grub_strlen (config) - slice_size] = '\0';
  1761. }
  1762. return 1;
  1763. }
  1764. grub_err_t
  1765. grub_net_search_config_file (char *config, grub_size_t config_buf_len)
  1766. {
  1767. grub_size_t config_len, suffix_len;
  1768. char *suffix;
  1769. config_len = grub_strlen (config);
  1770. config[config_len] = '-';
  1771. suffix = config + config_len + 1;
  1772. suffix_len = config_buf_len - (config_len + 1);
  1773. struct grub_net_network_level_interface *inf;
  1774. FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
  1775. {
  1776. /* By the Client UUID. */
  1777. char *ptr;
  1778. int client_uuid_len;
  1779. char *client_uuid_var;
  1780. const char *client_uuid;
  1781. client_uuid_len = sizeof ("net_") + grub_strlen (inf->name) +
  1782. sizeof ("_clientuuid") + 1;
  1783. client_uuid_var = grub_zalloc (client_uuid_len);
  1784. if (!client_uuid_var)
  1785. return grub_errno;
  1786. grub_snprintf (client_uuid_var, client_uuid_len,
  1787. "net_%s_clientuuid", inf->name);
  1788. client_uuid = grub_env_get (client_uuid_var);
  1789. grub_free (client_uuid_var);
  1790. if (client_uuid)
  1791. {
  1792. grub_strlcpy (suffix, client_uuid, suffix_len);
  1793. if (grub_config_search_through (config, suffix, 1, 0) == 0)
  1794. return GRUB_ERR_NONE;
  1795. }
  1796. /* By the MAC address. */
  1797. /* Add ethernet type */
  1798. grub_strcpy (suffix, "01-");
  1799. grub_net_hwaddr_to_str (&inf->hwaddress, suffix + 3);
  1800. for (ptr = suffix; *ptr; ptr++)
  1801. if (*ptr == ':')
  1802. *ptr = '-';
  1803. if (grub_config_search_through (config, suffix, 1, 0) == 0)
  1804. return GRUB_ERR_NONE;
  1805. /* By IP address */
  1806. switch ((&inf->address)->type)
  1807. {
  1808. case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4:
  1809. {
  1810. grub_uint32_t n = grub_be_to_cpu32 ((&inf->address)->ipv4);
  1811. grub_snprintf (suffix, GRUB_NET_MAX_STR_ADDR_LEN, "%02X%02X%02X%02X", \
  1812. ((n >> 24) & 0xff), ((n >> 16) & 0xff), \
  1813. ((n >> 8) & 0xff), ((n >> 0) & 0xff));
  1814. if (grub_config_search_through (config, suffix, 8, 1) == 0)
  1815. return GRUB_ERR_NONE;
  1816. break;
  1817. }
  1818. case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6:
  1819. {
  1820. char buf[GRUB_NET_MAX_STR_ADDR_LEN];
  1821. struct grub_net_network_level_address base;
  1822. base.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
  1823. grub_memcpy (&base.ipv6, ((&inf->address)->ipv6), 16);
  1824. grub_net_addr_to_str (&base, buf);
  1825. for (ptr = buf; *ptr; ptr++)
  1826. if (*ptr == ':')
  1827. *ptr = '-';
  1828. grub_snprintf (suffix, GRUB_NET_MAX_STR_ADDR_LEN, "%s", buf);
  1829. if (grub_config_search_through (config, suffix, 1, 0) == 0)
  1830. return GRUB_ERR_NONE;
  1831. break;
  1832. }
  1833. case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV:
  1834. return grub_error (GRUB_ERR_BUG, "shouldn't reach here");
  1835. default:
  1836. return grub_error (GRUB_ERR_BUG,
  1837. "unsupported address type %d", (&inf->address)->type);
  1838. }
  1839. }
  1840. /* Remove the remaining minus sign at the end. */
  1841. config[config_len] = '\0';
  1842. return GRUB_ERR_NONE;
  1843. }
  1844. static struct grub_preboot *fini_hnd;
  1845. static grub_command_t cmd_addaddr, cmd_deladdr, cmd_addroute, cmd_delroute;
  1846. static grub_command_t cmd_setvlan, cmd_lsroutes, cmd_lscards;
  1847. static grub_command_t cmd_lsaddr, cmd_slaac;
  1848. GRUB_MOD_INIT(net)
  1849. {
  1850. grub_register_variable_hook ("net_default_server", defserver_get_env,
  1851. defserver_set_env);
  1852. grub_env_export ("net_default_server");
  1853. grub_register_variable_hook ("pxe_default_server", defserver_get_env,
  1854. defserver_set_env);
  1855. grub_env_export ("pxe_default_server");
  1856. grub_register_variable_hook ("net_default_ip", defip_get_env,
  1857. defip_set_env);
  1858. grub_env_export ("net_default_ip");
  1859. grub_register_variable_hook ("net_default_mac", defmac_get_env,
  1860. defmac_set_env);
  1861. grub_env_export ("net_default_mac");
  1862. cmd_addaddr = grub_register_command ("net_add_addr", grub_cmd_addaddr,
  1863. /* TRANSLATORS: HWADDRESS stands for
  1864. "hardware address". */
  1865. N_("SHORTNAME CARD ADDRESS [HWADDRESS]"),
  1866. N_("Add a network address."));
  1867. cmd_slaac = grub_register_command ("net_ipv6_autoconf",
  1868. grub_cmd_ipv6_autoconf,
  1869. N_("[CARD [HWADDRESS]]"),
  1870. N_("Perform an IPV6 autoconfiguration"));
  1871. cmd_deladdr = grub_register_command ("net_del_addr", grub_cmd_deladdr,
  1872. N_("SHORTNAME"),
  1873. N_("Delete a network address."));
  1874. cmd_addroute = grub_register_command ("net_add_route", grub_cmd_addroute,
  1875. /* TRANSLATORS: "gw" is a keyword. */
  1876. N_("SHORTNAME NET [INTERFACE| gw GATEWAY]"),
  1877. N_("Add a network route."));
  1878. cmd_delroute = grub_register_command ("net_del_route", grub_cmd_delroute,
  1879. N_("SHORTNAME"),
  1880. N_("Delete a network route."));
  1881. cmd_setvlan = grub_register_command ("net_set_vlan", grub_cmd_setvlan,
  1882. N_("SHORTNAME VLANID"),
  1883. N_("Set an interface's vlan id."));
  1884. cmd_lsroutes = grub_register_command ("net_ls_routes", grub_cmd_listroutes,
  1885. "", N_("list network routes"));
  1886. cmd_lscards = grub_register_command ("net_ls_cards", grub_cmd_listcards,
  1887. "", N_("list network cards"));
  1888. cmd_lsaddr = grub_register_command ("net_ls_addr", grub_cmd_listaddrs,
  1889. "", N_("list network addresses"));
  1890. grub_bootp_init ();
  1891. grub_dns_init ();
  1892. grub_net_open = grub_net_open_real;
  1893. fini_hnd = grub_loader_register_preboot_hook (grub_net_fini_hw,
  1894. grub_net_restore_hw,
  1895. GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK);
  1896. grub_net_poll_cards_idle = grub_net_poll_cards_idle_real;
  1897. }
  1898. GRUB_MOD_FINI(net)
  1899. {
  1900. grub_register_variable_hook ("net_default_server", 0, 0);
  1901. grub_register_variable_hook ("pxe_default_server", 0, 0);
  1902. grub_register_variable_hook ("net_default_ip", 0, 0);
  1903. grub_register_variable_hook ("net_default_mac", 0, 0);
  1904. grub_bootp_fini ();
  1905. grub_dns_fini ();
  1906. grub_unregister_command (cmd_addaddr);
  1907. grub_unregister_command (cmd_deladdr);
  1908. grub_unregister_command (cmd_addroute);
  1909. grub_unregister_command (cmd_delroute);
  1910. grub_unregister_command (cmd_lsroutes);
  1911. grub_unregister_command (cmd_lscards);
  1912. grub_unregister_command (cmd_lsaddr);
  1913. grub_unregister_command (cmd_slaac);
  1914. grub_fs_unregister (&grub_net_fs);
  1915. grub_net_open = NULL;
  1916. grub_net_fini_hw (0);
  1917. grub_loader_unregister_preboot_hook (fini_hnd);
  1918. grub_net_poll_cards_idle = NULL;
  1919. }