1 /**************************************************************************
2 Etherboot - Network Bootstrap Program
4 Literature dealing with the network protocols:
9 BOOTP - RFC951, RFC2132 (vendor extensions)
10 DHCP - RFC2131, RFC2132 (options)
11 TFTP - RFC1350, RFC2347 (options), RFC2348 (blocksize), RFC2349 (tsize)
12 RPC - RFC1831, RFC1832 (XDR), RFC1833 (rpcbind/portmapper)
13 NFS - RFC1094, RFC1813 (v3, useful for clarifications, not implemented)
14 IGMP - RFC1112, RFC2113, RFC2365, RFC2236, RFC3171
16 **************************************************************************/
17 #include "etherboot.h"
20 #include "elf.h" /* FOR EM_CURRENT */
28 /* Currently no other module uses rom, but it is available */
30 struct arptable_t arptable
[MAX_ARP
];
31 #ifdef MULTICAST_LEVEL2
32 unsigned long last_igmpv1
= 0;
33 struct igmptable_t igmptable
[MAX_IGMP
];
35 static unsigned long netmask
;
39 /* Used by fsys_tftp.c */
42 static unsigned char *end_of_rfc1533
= NULL
;
43 static const unsigned char broadcast
[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
44 static const in_addr zeroIP
= { 0L };
45 static char rfc1533_venddata
[MAX_RFC1533_VENDLEN
];
46 static unsigned char rfc1533_cookie
[4] = { RFC1533_COOKIE
};
47 static unsigned char rfc1533_cookie_bootp
[5] = { RFC1533_COOKIE
, RFC1533_END
};
48 static unsigned char rfc1533_cookie_dhcp
[] = { RFC1533_COOKIE
};
49 static int dhcp_reply
;
50 static in_addr dhcp_server
= { 0L };
51 static in_addr dhcp_addr
= { 0L };
53 static const unsigned char dhcpdiscover
[] = {
54 RFC2132_MSG_TYPE
, 1, DHCPDISCOVER
,
55 RFC2132_MAX_SIZE
, 2, /* request as much as we can */
56 ETH_MAX_MTU
/ 256, ETH_MAX_MTU
% 256,
57 /* Vendor class identifier */
58 #ifdef SOLARIS_NETBOOT
59 RFC2132_VENDOR_CLASS_ID
,32,'P','X','E','C','l','i','e','n','t',':',
60 'A','r','c','h',':','0','0','0','0','0',':','U','N','D','I',':',
61 '0','0','2','0','0','1',
63 RFC2132_VENDOR_CLASS_ID
, 10, 'G', 'R', 'U', 'B', 'C', 'l', 'i', 'e', 'n', 't',
65 RFC2132_PARAM_LIST
, 4, RFC1533_NETMASK
, RFC1533_GATEWAY
,
66 RFC1533_HOSTNAME
, RFC1533_EXTENSIONPATH
, RFC1533_END
68 static const unsigned char dhcprequest
[] = {
69 RFC2132_MSG_TYPE
,1,DHCPREQUEST
,
70 RFC2132_SRV_ID
,4,0,0,0,0,
71 RFC2132_REQ_ADDR
,4,0,0,0,0,
72 RFC2132_MAX_SIZE
,2, /* request as much as we can */
73 ETH_MAX_MTU
/ 256, ETH_MAX_MTU
% 256,
74 /* Vendor class identifier */
75 #ifdef SOLARIS_NETBOOT
76 RFC2132_VENDOR_CLASS_ID
,32,'P','X','E','C','l','i','e','n','t',':',
77 'A','r','c','h',':','0','0','0','0','0',':','U','N','D','I',':',
78 '0','0','2','0','0','1',
80 RFC2132_VENDOR_CLASS_ID
, 10, 'G', 'R', 'U', 'B', 'C', 'l', 'i', 'e', 'n', 't',
83 /* 4 standard + 2 vendortags */
85 /* Standard parameters */
86 RFC1533_NETMASK
, RFC1533_GATEWAY
,
87 RFC1533_HOSTNAME
, RFC1533_EXTENSIONPATH
,
88 /* Etherboot vendortags */
90 RFC1533_VENDOR_CONFIGFILE
,
96 int network_ready
= 0;
98 #ifdef REQUIRE_VCI_ETHERBOOT
102 char *bootfile
= NULL
;
103 configfile_origin_t configfile_origin
= CFG_HARDCODED
;
104 char *vendor_configfile
= NULL
;
105 char vendor_configfile_len
;
107 static void update_network_configuration(void);
109 static int dummy(void *unused __unused
)
114 /* Careful. We need an aligned buffer to avoid problems on machines
115 * that care about alignment. To trivally align the ethernet data
116 * (the ip hdr and arp requests) we offset the packet by 2 bytes.
117 * leaving the ethernet data 16 byte aligned. Beyond this
118 * we use memmove but this makes the common cast simple and fast.
120 static char packet
[ETH_FRAME_LEN
+ ETH_DATA_ALIGN
] __aligned
;
133 PROBE_FIRST
, /* how_pobe */
134 PROBE_NONE
, /* to_probe */
139 (int (*)(struct nic
*, int))dummy
, /* poll */
140 (void (*)(struct nic
*, const char *,
141 unsigned int, unsigned int,
142 const char *))dummy
, /* transmit */
143 (void (*)(struct nic
*, irq_action_t
))dummy
, /* irq */
146 arptable
[ARP_CLIENT
].node
, /* node_addr */
147 packet
+ ETH_DATA_ALIGN
, /* packet */
151 NULL
, /* priv_data */
156 int grub_eth_probe(void)
158 static int probed
= 0;
161 EnterFunction("grub_eth_probe");
167 grub_memset((char *)arptable
, 0, MAX_ARP
* sizeof(struct arptable_t
));
170 dev
->type
= NIC_DRIVER
;
172 rom
= *((struct rom_info
*)ROM_INFO_LOCATION
);
174 probed
= (eth_probe(dev
) == PROBE_WORKED
);
176 LeaveFunction("grub_eth_probe");
180 int eth_probe(struct dev
*dev
)
185 int eth_poll(int retrieve
)
187 return ((*nic
.poll
)(&nic
, retrieve
));
190 void eth_transmit(const char *d
, unsigned int t
, unsigned int s
, const void *p
)
192 (*nic
.transmit
)(&nic
, d
, t
, s
, p
);
193 if (t
== IP
) twiddle();
196 void eth_disable(void)
198 #ifdef MULTICAST_LEVEL2
200 for(i
= 0; i
< MAX_IGMP
; i
++) {
207 void eth_irq (irq_action_t action
)
209 (*nic
.irq
)(&nic
,action
);
212 /**************************************************************************
213 IPCHKSUM - Checksum IP Header
214 **************************************************************************/
215 uint16_t ipchksum(const void *data
, unsigned long length
)
221 /* In the most straight forward way possible,
222 * compute an ip style checksum.
226 for(i
= 0; i
< length
; i
++) {
232 /* Add the new value */
234 /* Wrap around the carry */
236 sum
= (sum
+ (sum
>> 16)) & 0xFFFF;
239 return (~cpu_to_le16(sum
)) & 0xFFFF;
242 uint16_t add_ipchksums(unsigned long offset
, uint16_t sum
, uint16_t new)
244 unsigned long checksum
;
248 /* byte swap the sum if it came from an odd offset
249 * since the computation is endian independant this
254 checksum
= sum
+ new;
255 if (checksum
> 0xFFFF) {
258 return (~checksum
) & 0xFFFF;
261 /**************************************************************************
262 DEFAULT_NETMASK - Return default netmask for IP address
263 **************************************************************************/
264 static inline unsigned long default_netmask(void)
266 int net
= ntohl(arptable
[ARP_CLIENT
].ipaddr
.s_addr
) >> 24;
268 return(htonl(0xff000000));
270 return(htonl(0xffff0000));
272 return(htonl(0xffffff00));
275 /**************************************************************************
276 IP_TRANSMIT - Send an IP datagram
277 **************************************************************************/
278 static int await_arp(int ival
, void *ptr
,
279 unsigned short ptype
, struct iphdr
*ip __unused
, struct udphdr
*udp __unused
)
281 struct arprequest
*arpreply
;
284 if (nic
.packetlen
< ETH_HLEN
+ sizeof(struct arprequest
))
286 arpreply
= (struct arprequest
*)&nic
.packet
[ETH_HLEN
];
288 if (arpreply
->opcode
!= htons(ARP_REPLY
))
290 if (memcmp(arpreply
->sipaddr
, ptr
, sizeof(in_addr
)) != 0)
292 memcpy(arptable
[ival
].node
, arpreply
->shwaddr
, ETH_ALEN
);
296 int ip_transmit(int len
, const void *buf
)
298 unsigned long destip
;
300 struct arprequest arpreq
;
304 ip
= (struct iphdr
*)buf
;
305 destip
= ip
->dest
.s_addr
;
306 if (destip
== IP_BROADCAST
) {
307 eth_transmit(broadcast
, IP
, len
, buf
);
308 #ifdef MULTICAST_LEVEL1
309 } else if ((destip
& htonl(MULTICAST_MASK
)) == htonl(MULTICAST_NETWORK
)) {
310 unsigned char multicast
[6];
311 unsigned long hdestip
;
312 hdestip
= ntohl(destip
);
316 multicast
[3] = (hdestip
>> 16) & 0x7;
317 multicast
[4] = (hdestip
>> 8) & 0xff;
318 multicast
[5] = hdestip
& 0xff;
319 eth_transmit(multicast
, IP
, len
, buf
);
322 if (((destip
& netmask
) !=
323 (arptable
[ARP_CLIENT
].ipaddr
.s_addr
& netmask
)) &&
324 arptable
[ARP_GATEWAY
].ipaddr
.s_addr
)
325 destip
= arptable
[ARP_GATEWAY
].ipaddr
.s_addr
;
326 for(arpentry
= 0; arpentry
<MAX_ARP
; arpentry
++)
327 if (arptable
[arpentry
].ipaddr
.s_addr
== destip
) break;
328 if (arpentry
== MAX_ARP
) {
329 printf("%@ is not in my arp table!\n", destip
);
332 for (i
= 0; i
< ETH_ALEN
; i
++)
333 if (arptable
[arpentry
].node
[i
])
335 if (i
== ETH_ALEN
) { /* Need to do arp request */
336 arpreq
.hwtype
= htons(1);
337 arpreq
.protocol
= htons(IP
);
338 arpreq
.hwlen
= ETH_ALEN
;
340 arpreq
.opcode
= htons(ARP_REQUEST
);
341 memcpy(arpreq
.shwaddr
, arptable
[ARP_CLIENT
].node
, ETH_ALEN
);
342 memcpy(arpreq
.sipaddr
, &arptable
[ARP_CLIENT
].ipaddr
, sizeof(in_addr
));
343 memset(arpreq
.thwaddr
, 0, ETH_ALEN
);
344 memcpy(arpreq
.tipaddr
, &destip
, sizeof(in_addr
));
345 for (retry
= 1; retry
<= MAX_ARP_RETRIES
; retry
++) {
347 eth_transmit(broadcast
, ARP
, sizeof(arpreq
),
349 timeout
= rfc2131_sleep_interval(TIMEOUT
, retry
);
350 if (await_reply(await_arp
, arpentry
,
351 arpreq
.tipaddr
, timeout
)) goto xmit
;
356 eth_transmit(arptable
[arpentry
].node
, IP
, len
, buf
);
361 void build_ip_hdr(unsigned long destip
, int ttl
, int protocol
, int option_len
,
362 int len
, const void *buf
)
365 ip
= (struct iphdr
*)buf
;
366 ip
->verhdrlen
= 0x45;
367 ip
->verhdrlen
+= (option_len
/4);
369 ip
->len
= htons(len
);
371 ip
->frags
= 0; /* Should we set don't fragment? */
373 ip
->protocol
= protocol
;
375 ip
->src
.s_addr
= arptable
[ARP_CLIENT
].ipaddr
.s_addr
;
376 ip
->dest
.s_addr
= destip
;
377 ip
->chksum
= ipchksum(buf
, sizeof(struct iphdr
) + option_len
);
380 static uint16_t udpchksum(struct iphdr
*ip
, struct udphdr
*udp
)
382 struct udp_pseudo_hdr pseudo
;
385 /* Compute the pseudo header */
386 pseudo
.src
.s_addr
= ip
->src
.s_addr
;
387 pseudo
.dest
.s_addr
= ip
->dest
.s_addr
;
389 pseudo
.protocol
= IP_UDP
;
390 pseudo
.len
= udp
->len
;
392 /* Sum the pseudo header */
393 checksum
= ipchksum(&pseudo
, 12);
395 /* Sum the rest of the udp packet */
396 checksum
= add_ipchksums(12, checksum
, ipchksum(udp
, ntohs(udp
->len
)));
401 void build_udp_hdr(unsigned long destip
,
402 unsigned int srcsock
, unsigned int destsock
, int ttl
,
403 int len
, const void *buf
)
407 ip
= (struct iphdr
*)buf
;
408 build_ip_hdr(destip
, ttl
, IP_UDP
, 0, len
, buf
);
409 udp
= (struct udphdr
*)((char *)buf
+ sizeof(struct iphdr
));
410 udp
->src
= htons(srcsock
);
411 udp
->dest
= htons(destsock
);
412 udp
->len
= htons(len
- sizeof(struct iphdr
));
414 if ((udp
->chksum
= udpchksum(ip
, udp
)) == 0)
415 udp
->chksum
= 0xffff;
419 /**************************************************************************
420 UDP_TRANSMIT - Send an UDP datagram
421 **************************************************************************/
422 int udp_transmit(unsigned long destip
, unsigned int srcsock
,
423 unsigned int destsock
, int len
, const void *buf
)
425 build_udp_hdr(destip
, srcsock
, destsock
, 60, len
, buf
);
426 return ip_transmit(len
, buf
);
429 /**************************************************************************
430 QDRAIN - clear the nic's receive queue
431 **************************************************************************/
432 static int await_qdrain(int ival __unused
, void *ptr __unused
,
433 unsigned short ptype __unused
,
434 struct iphdr
*ip __unused
, struct udphdr
*udp __unused
)
441 /* Clear out the Rx queue first. It contains nothing of interest,
442 * except possibly ARP requests from the DHCP/TFTP server. We use
443 * polling throughout Etherboot, so some time may have passed since we
444 * last polled the receive queue, which may now be filled with
445 * broadcast packets. This will cause the reply to the packets we are
446 * about to send to be lost immediately. Not very clever. */
447 await_reply(await_qdrain
, 0, NULL
, 0);
453 * Get IP address by rarp. Just copy from etherboot
455 static int await_rarp(int ival
, void *ptr
, unsigned short ptype
,
456 struct iphdr
*ip
, struct udphdr
*udp
)
458 struct arprequest
*arpreply
;
461 if (nic
.packetlen
< ETH_HLEN
+ sizeof(struct arprequest
))
463 arpreply
= (struct arprequest
*)&nic
.packet
[ETH_HLEN
];
464 if (arpreply
->opcode
!= htons(RARP_REPLY
))
466 if (memcmp(arpreply
->thwaddr
, ptr
, ETH_ALEN
) == 0){
467 memcpy(arptable
[ARP_SERVER
].node
, arpreply
->shwaddr
, ETH_ALEN
);
468 memcpy(&arptable
[ARP_SERVER
].ipaddr
, arpreply
->sipaddr
, sizeof(in_addr
));
469 memcpy(&arptable
[ARP_CLIENT
].ipaddr
, arpreply
->tipaddr
, sizeof(in_addr
));
470 memset(&arptable
[ARP_GATEWAY
].ipaddr
, 0, sizeof(in_addr
));
480 /* arp and rarp requests share the same packet structure. */
481 struct arprequest rarpreq
;
483 if(!grub_eth_probe())
487 memset(&rarpreq
, 0, sizeof(rarpreq
));
489 rarpreq
.hwtype
= htons(1);
490 rarpreq
.protocol
= htons(IP
);
491 rarpreq
.hwlen
= ETH_ALEN
;
492 rarpreq
.protolen
= 4;
493 rarpreq
.opcode
= htons(RARP_REQUEST
);
494 memcpy(&rarpreq
.shwaddr
, arptable
[ARP_CLIENT
].node
, ETH_ALEN
);
495 /* sipaddr is already zeroed out */
496 memcpy(&rarpreq
.thwaddr
, arptable
[ARP_CLIENT
].node
, ETH_ALEN
);
497 /* tipaddr is already zeroed out */
499 for (retry
= 0; retry
< MAX_ARP_RETRIES
; ++retry
) {
501 eth_transmit(broadcast
, RARP
, sizeof(rarpreq
), &rarpreq
);
503 timeout
= rfc2131_sleep_interval(TIMEOUT
, retry
);
504 if (await_reply(await_rarp
, 0, rarpreq
.shwaddr
, timeout
))
510 if (retry
== MAX_ARP_RETRIES
) {
515 update_network_configuration();
522 * Get IP address by bootp, segregate from bootp in etherboot.
524 static int await_bootp(int ival __unused
, void *ptr __unused
,
525 unsigned short ptype __unused
, struct iphdr
*ip __unused
,
528 struct bootp_t
*bootpreply
;
529 int len
; /* Length of vendor */
534 bootpreply
= (struct bootp_t
*)
535 &nic
.packet
[ETH_HLEN
+ sizeof(struct iphdr
) + sizeof(struct udphdr
)];
536 len
= nic
.packetlen
- (ETH_HLEN
+ sizeof(struct iphdr
) +
537 sizeof(struct udphdr
) + sizeof(struct bootp_t
) - BOOTP_VENDOR_LEN
);
541 if (udp
->dest
!= htons(BOOTP_CLIENT
))
543 if (bootpreply
->bp_op
!= BOOTP_REPLY
)
545 if (bootpreply
->bp_xid
!= xid
)
547 if (memcmp((char *)&bootpreply
->bp_siaddr
, (char *)&zeroIP
, sizeof(in_addr
)) == 0)
549 if ((memcmp(broadcast
, bootpreply
->bp_hwaddr
, ETH_ALEN
) != 0) &&
550 (memcmp(arptable
[ARP_CLIENT
].node
, bootpreply
->bp_hwaddr
, ETH_ALEN
) != 0)) {
554 #ifdef SOLARIS_NETBOOT
555 /* fill in netinfo */
556 dhcpack_length
= len
+ sizeof (struct bootp_t
) - BOOTP_VENDOR_LEN
;
557 memcpy((char *)dhcpack_buf
, (char *)bootpreply
, dhcpack_length
);
560 arptable
[ARP_CLIENT
].ipaddr
.s_addr
= bootpreply
->bp_yiaddr
.s_addr
;
561 netmask
= default_netmask();
562 arptable
[ARP_SERVER
].ipaddr
.s_addr
= bootpreply
->bp_siaddr
.s_addr
;
563 memset(arptable
[ARP_SERVER
].node
, 0, ETH_ALEN
); /* Kill arp */
564 arptable
[ARP_GATEWAY
].ipaddr
.s_addr
= bootpreply
->bp_giaddr
.s_addr
;
565 memset(arptable
[ARP_GATEWAY
].node
, 0, ETH_ALEN
); /* Kill arp */
566 bootfile
= bootpreply
->bp_file
;
567 memcpy((char *)rfc1533_venddata
, (char *)(bootpreply
->bp_vend
), len
);
568 decode_rfc1533(rfc1533_venddata
, 0, len
, 1);
576 unsigned long starttime
;
578 EnterFunction("bootp");
580 if(!grub_eth_probe())
584 memset(&ip
, 0, sizeof(struct bootpip_t
));
585 ip
.bp
.bp_op
= BOOTP_REQUEST
;
587 ip
.bp
.bp_hlen
= ETH_ALEN
;
588 starttime
= currticks();
589 /* Use lower 32 bits of node address, more likely to be
590 distinct than the time since booting */
591 memcpy(&xid
, &arptable
[ARP_CLIENT
].node
[2], sizeof(xid
));
592 ip
.bp
.bp_xid
= xid
+= htonl(starttime
);
593 /* bp_secs defaults to zero */
594 memcpy(ip
.bp
.bp_hwaddr
, arptable
[ARP_CLIENT
].node
, ETH_ALEN
);
595 memcpy(ip
.bp
.bp_vend
, rfc1533_cookie_bootp
, sizeof(rfc1533_cookie_bootp
)); /* request RFC-style options */
597 for (retry
= 0; retry
< MAX_BOOTP_RETRIES
; ) {
602 udp_transmit(IP_BROADCAST
, BOOTP_CLIENT
, BOOTP_SERVER
,
603 sizeof(struct bootpip_t
), &ip
);
604 timeout
= rfc2131_sleep_interval(TIMEOUT
, retry
++);
605 if (await_reply(await_bootp
, 0, NULL
, timeout
)){
611 ip
.bp
.bp_secs
= htons((currticks()-starttime
)/TICKS_PER_SEC
);
619 * Get IP address by dhcp, segregate from bootp in etherboot.
621 static int await_dhcp(int ival __unused
, void *ptr __unused
,
622 unsigned short ptype __unused
, struct iphdr
*ip __unused
,
625 struct dhcp_t
*dhcpreply
;
631 dhcpreply
= (struct dhcp_t
*)
632 &nic
.packet
[ETH_HLEN
+ sizeof(struct iphdr
) + sizeof(struct udphdr
)];
633 len
= nic
.packetlen
- (ETH_HLEN
+ sizeof(struct iphdr
) +
634 sizeof(struct udphdr
) + sizeof(struct dhcp_t
) - DHCP_OPT_LEN
);
638 if (udp
->dest
!= htons(BOOTP_CLIENT
))
640 if (dhcpreply
->bp_op
!= BOOTP_REPLY
)
642 if (dhcpreply
->bp_xid
!= xid
)
644 if (memcmp((char *)&dhcpreply
->bp_siaddr
, (char *)&zeroIP
, sizeof(in_addr
)) == 0)
646 if ((memcmp(broadcast
, dhcpreply
->bp_hwaddr
, ETH_ALEN
) != 0) &&
647 (memcmp(arptable
[ARP_CLIENT
].node
, dhcpreply
->bp_hwaddr
, ETH_ALEN
) != 0)) {
651 #ifdef SOLARIS_NETBOOT
652 /* fill in netinfo */
653 dhcpack_length
= len
+ sizeof (struct dhcp_t
) - DHCP_OPT_LEN
;
654 memcpy((char *)dhcpack_buf
, (char *)dhcpreply
, dhcpack_length
);
656 arptable
[ARP_CLIENT
].ipaddr
.s_addr
= dhcpreply
->bp_yiaddr
.s_addr
;
657 dhcp_addr
.s_addr
= dhcpreply
->bp_yiaddr
.s_addr
;
658 netmask
= default_netmask();
659 arptable
[ARP_SERVER
].ipaddr
.s_addr
= dhcpreply
->bp_siaddr
.s_addr
;
660 memset(arptable
[ARP_SERVER
].node
, 0, ETH_ALEN
); /* Kill arp */
661 arptable
[ARP_GATEWAY
].ipaddr
.s_addr
= dhcpreply
->bp_giaddr
.s_addr
;
662 memset(arptable
[ARP_GATEWAY
].node
, 0, ETH_ALEN
); /* Kill arp */
663 bootfile
= dhcpreply
->bp_file
;
664 memcpy((char *)rfc1533_venddata
, (char *)(dhcpreply
->bp_vend
), len
);
665 decode_rfc1533(rfc1533_venddata
, 0, len
, 1);
674 unsigned long starttime
;
676 /* try bios pxe stack first */
680 if(!grub_eth_probe())
685 memset(&ip
, 0, sizeof(ip
));
686 ip
.bp
.bp_op
= BOOTP_REQUEST
;
688 ip
.bp
.bp_hlen
= ETH_ALEN
;
689 starttime
= currticks();
690 /* Use lower 32 bits of node address, more likely to be
691 distinct than the time since booting */
692 memcpy(&xid
, &arptable
[ARP_CLIENT
].node
[2], sizeof(xid
));
693 ip
.bp
.bp_xid
= xid
+= htonl(starttime
);
694 memcpy(ip
.bp
.bp_hwaddr
, arptable
[ARP_CLIENT
].node
, ETH_ALEN
);
695 memcpy(ip
.bp
.bp_vend
, rfc1533_cookie_dhcp
, sizeof rfc1533_cookie_dhcp
); /* request RFC-style options */
696 memcpy(ip
.bp
.bp_vend
+ sizeof rfc1533_cookie_dhcp
, dhcpdiscover
, sizeof dhcpdiscover
);
698 for (retry
= 0; retry
< MAX_BOOTP_RETRIES
; ) {
703 udp_transmit(IP_BROADCAST
, BOOTP_CLIENT
, BOOTP_SERVER
,
705 timeout
= rfc2131_sleep_interval(TIMEOUT
, retry
++);
706 if (await_reply(await_dhcp
, 0, NULL
, timeout
)) {
707 /* If not a DHCPOFFER then must be just a
708 BOOTP reply, be backward compatible with
709 BOOTP then. Jscott report a bug here, but I
710 don't know how it happened */
711 if (dhcp_reply
!= DHCPOFFER
){
716 memcpy(ip
.bp
.bp_vend
, rfc1533_cookie_dhcp
, sizeof rfc1533_cookie_dhcp
);
717 memcpy(ip
.bp
.bp_vend
+ sizeof rfc1533_cookie_dhcp
, dhcprequest
, sizeof dhcprequest
);
718 /* Beware: the magic numbers 9 and 15 depend on
719 the layout of dhcprequest */
720 memcpy(&ip
.bp
.bp_vend
[9], &dhcp_server
, sizeof(in_addr
));
721 memcpy(&ip
.bp
.bp_vend
[15], &dhcp_addr
, sizeof(in_addr
));
722 for (reqretry
= 0; reqretry
< MAX_BOOTP_RETRIES
; ) {
723 udp_transmit(IP_BROADCAST
, BOOTP_CLIENT
, BOOTP_SERVER
,
726 timeout
= rfc2131_sleep_interval(TIMEOUT
, reqretry
++);
727 if (await_reply(await_dhcp
, 0, NULL
, timeout
))
728 if (dhcp_reply
== DHCPACK
){
738 ip
.bp
.bp_secs
= htons((currticks()-starttime
)/TICKS_PER_SEC
);
743 #ifdef MULTICAST_LEVEL2
744 static void send_igmp_reports(unsigned long now
)
747 for(i
= 0; i
< MAX_IGMP
; i
++) {
748 if (igmptable
[i
].time
&& (now
>= igmptable
[i
].time
)) {
749 struct igmp_ip_t igmp
;
750 igmp
.router_alert
[0] = 0x94;
751 igmp
.router_alert
[1] = 0x04;
752 igmp
.router_alert
[2] = 0;
753 igmp
.router_alert
[3] = 0;
754 build_ip_hdr(igmptable
[i
].group
.s_addr
,
755 1, IP_IGMP
, sizeof(igmp
.router_alert
), sizeof(igmp
), &igmp
);
756 igmp
.igmp
.type
= IGMPv2_REPORT
;
758 (now
< last_igmpv1
+ IGMPv1_ROUTER_PRESENT_TIMEOUT
)) {
759 igmp
.igmp
.type
= IGMPv1_REPORT
;
761 igmp
.igmp
.response_time
= 0;
762 igmp
.igmp
.chksum
= 0;
763 igmp
.igmp
.group
.s_addr
= igmptable
[i
].group
.s_addr
;
764 igmp
.igmp
.chksum
= ipchksum(&igmp
.igmp
, sizeof(igmp
.igmp
));
765 ip_transmit(sizeof(igmp
), &igmp
);
767 printf("Sent IGMP report to: %@\n", igmp
.igmp
.group
.s_addr
);
769 /* Don't send another igmp report until asked */
770 igmptable
[i
].time
= 0;
775 static void process_igmp(struct iphdr
*ip
, unsigned long now
)
780 if (!ip
|| (ip
->protocol
== IP_IGMP
) ||
781 (nic
.packetlen
< sizeof(struct iphdr
) + sizeof(struct igmp
))) {
784 iplen
= (ip
->verhdrlen
& 0xf)*4;
785 igmp
= (struct igmp
*)&nic
.packet
[sizeof(struct iphdr
)];
786 if (ipchksum(igmp
, ntohs(ip
->len
) - iplen
) != 0)
788 if ((igmp
->type
== IGMP_QUERY
) &&
789 (ip
->dest
.s_addr
== htonl(GROUP_ALL_HOSTS
))) {
790 unsigned long interval
= IGMP_INTERVAL
;
791 if (igmp
->response_time
== 0) {
794 interval
= (igmp
->response_time
* TICKS_PER_SEC
)/10;
798 printf("Received IGMP query for: %@\n", igmp
->group
.s_addr
);
800 for(i
= 0; i
< MAX_IGMP
; i
++) {
801 uint32_t group
= igmptable
[i
].group
.s_addr
;
802 if ((group
== 0) || (group
== igmp
->group
.s_addr
)) {
804 time
= currticks() + rfc1112_sleep_interval(interval
, 0);
805 if (time
< igmptable
[i
].time
) {
806 igmptable
[i
].time
= time
;
811 if (((igmp
->type
== IGMPv1_REPORT
) || (igmp
->type
== IGMPv2_REPORT
)) &&
812 (ip
->dest
.s_addr
== igmp
->group
.s_addr
)) {
814 printf("Received IGMP report for: %@\n", igmp
->group
.s_addr
);
816 for(i
= 0; i
< MAX_IGMP
; i
++) {
817 if ((igmptable
[i
].group
.s_addr
== igmp
->group
.s_addr
) &&
818 igmptable
[i
].time
!= 0) {
819 igmptable
[i
].time
= 0;
825 void leave_group(int slot
)
827 /* Be very stupid and always send a leave group message if
828 * I have subscribed. Imperfect but it is standards
829 * compliant, easy and reliable to implement.
831 * The optimal group leave method is to only send leave when,
832 * we were the last host to respond to a query on this group,
833 * and igmpv1 compatibility is not enabled.
835 if (igmptable
[slot
].group
.s_addr
) {
836 struct igmp_ip_t igmp
;
837 igmp
.router_alert
[0] = 0x94;
838 igmp
.router_alert
[1] = 0x04;
839 igmp
.router_alert
[2] = 0;
840 igmp
.router_alert
[3] = 0;
841 build_ip_hdr(htonl(GROUP_ALL_HOSTS
),
842 1, IP_IGMP
, sizeof(igmp
.router_alert
), sizeof(igmp
), &igmp
);
843 igmp
.igmp
.type
= IGMP_LEAVE
;
844 igmp
.igmp
.response_time
= 0;
845 igmp
.igmp
.chksum
= 0;
846 igmp
.igmp
.group
.s_addr
= igmptable
[slot
].group
.s_addr
;
847 igmp
.igmp
.chksum
= ipchksum(&igmp
.igmp
, sizeof(igmp
));
848 ip_transmit(sizeof(igmp
), &igmp
);
850 printf("Sent IGMP leave for: %@\n", igmp
.igmp
.group
.s_addr
);
853 memset(&igmptable
[slot
], 0, sizeof(igmptable
[0]));
856 void join_group(int slot
, unsigned long group
)
858 /* I have already joined */
859 if (igmptable
[slot
].group
.s_addr
== group
)
861 if (igmptable
[slot
].group
.s_addr
) {
864 /* Only join a group if we are given a multicast ip, this way
865 * code can be given a non-multicast (broadcast or unicast ip)
868 if ((group
& htonl(MULTICAST_MASK
)) == htonl(MULTICAST_NETWORK
)) {
869 igmptable
[slot
].group
.s_addr
= group
;
870 igmptable
[slot
].time
= currticks();
874 #define send_igmp_reports(now);
875 #define process_igmp(ip, now)
878 /**************************************************************************
879 AWAIT_REPLY - Wait until we get a response for our request
880 ************f**************************************************************/
881 int await_reply(reply_t reply
, int ival
, void *ptr
, long timeout
)
883 unsigned long time
, now
;
887 unsigned short ptype
;
892 time
= timeout
+ currticks();
893 /* The timeout check is done below. The timeout is only checked if
894 * there is no packet in the Rx queue. This assumes that eth_poll()
895 * needs a negligible amount of time.
899 send_igmp_reports(now
);
900 result
= eth_poll(1);
902 /* We don't have anything */
904 /* Check for abort key only if the Rx queue is empty -
905 * as long as we have something to process, don't
906 * assume that something failed. It is unlikely that
907 * we have no processing time left between packets. */
908 poll_interruptions();
909 /* Do the timeout after at least a full queue walk. */
910 if ((timeout
== 0) || (currticks() > time
) || user_abort
== 1) {
916 /* We have something! */
918 /* Find the Ethernet packet type */
919 if (nic
.packetlen
>= ETH_HLEN
) {
920 ptype
= ((unsigned short) nic
.packet
[12]) << 8
921 | ((unsigned short) nic
.packet
[13]);
922 } else continue; /* what else could we do with it? */
923 /* Verify an IP header */
925 if ((ptype
== IP
) && (nic
.packetlen
>= ETH_HLEN
+ sizeof(struct iphdr
))) {
927 ip
= (struct iphdr
*)&nic
.packet
[ETH_HLEN
];
928 if ((ip
->verhdrlen
< 0x45) || (ip
->verhdrlen
> 0x4F))
930 iplen
= (ip
->verhdrlen
& 0xf) * 4;
931 if (ipchksum(ip
, iplen
) != 0)
933 if (ip
->frags
& htons(0x3FFF)) {
934 static int warned_fragmentation
= 0;
935 if (!warned_fragmentation
) {
936 printf("ALERT: got a fragmented packet - reconfigure your server\n");
937 warned_fragmentation
= 1;
941 if (ntohs(ip
->len
) > ETH_MAX_MTU
)
944 ipoptlen
= iplen
- sizeof(struct iphdr
);
946 /* Delete the ip options, to guarantee
947 * good alignment, and make etherboot simpler.
949 memmove(&nic
.packet
[ETH_HLEN
+ sizeof(struct iphdr
)],
950 &nic
.packet
[ETH_HLEN
+ iplen
],
951 nic
.packetlen
- ipoptlen
);
952 nic
.packetlen
-= ipoptlen
;
956 if (ip
&& (ip
->protocol
== IP_UDP
) &&
957 (nic
.packetlen
>= ETH_HLEN
+ sizeof(struct iphdr
) + sizeof(struct udphdr
))) {
958 udp
= (struct udphdr
*)&nic
.packet
[ETH_HLEN
+ sizeof(struct iphdr
)];
960 /* Make certain we have a reasonable packet length */
961 if (ntohs(udp
->len
) > (ntohs(ip
->len
) - iplen
))
964 if (udp
->chksum
&& udpchksum(ip
, udp
)) {
965 printf("UDP checksum error\n");
969 result
= reply(ival
, ptr
, ptype
, ip
, udp
);
974 /* If it isn't a packet the upper layer wants see if there is a default
975 * action. This allows us reply to arp and igmp queryies.
977 if ((ptype
== ARP
) &&
978 (nic
.packetlen
>= ETH_HLEN
+ sizeof(struct arprequest
))) {
979 struct arprequest
*arpreply
;
982 arpreply
= (struct arprequest
*)&nic
.packet
[ETH_HLEN
];
983 memcpy(&tmp
, arpreply
->tipaddr
, sizeof(in_addr
));
984 if ((arpreply
->opcode
== htons(ARP_REQUEST
)) &&
985 (tmp
== arptable
[ARP_CLIENT
].ipaddr
.s_addr
)) {
986 arpreply
->opcode
= htons(ARP_REPLY
);
987 memcpy(arpreply
->tipaddr
, arpreply
->sipaddr
, sizeof(in_addr
));
988 memcpy(arpreply
->thwaddr
, arpreply
->shwaddr
, ETH_ALEN
);
989 memcpy(arpreply
->sipaddr
, &arptable
[ARP_CLIENT
].ipaddr
, sizeof(in_addr
));
990 memcpy(arpreply
->shwaddr
, arptable
[ARP_CLIENT
].node
, ETH_ALEN
);
991 eth_transmit(arpreply
->thwaddr
, ARP
,
992 sizeof(struct arprequest
),
995 memcpy(&tmp
, arpreply
->tipaddr
, sizeof(in_addr
));
996 printf("Sent ARP reply to: %@\n",tmp
);
1000 process_igmp(ip
, now
);
1005 #ifdef REQUIRE_VCI_ETHERBOOT
1006 /**************************************************************************
1007 FIND_VCI_ETHERBOOT - Looks for "Etherboot" in Vendor Encapsulated Identifiers
1008 On entry p points to byte count of VCI options
1009 **************************************************************************/
1010 static int find_vci_etherboot(unsigned char *p
)
1012 unsigned char *end
= p
+ 1 + *p
;
1014 for (p
++; p
< end
; ) {
1015 if (*p
== RFC2132_VENDOR_CLASS_ID
) {
1016 if (strncmp("Etherboot", p
+ 2, sizeof("Etherboot") - 1) == 0)
1018 } else if (*p
== RFC1533_END
)
1020 p
+= TAG_LEN(p
) + 2;
1024 #endif /* REQUIRE_VCI_ETHERBOOT */
1029 * Decodes RFC1533 header
1031 int decode_rfc1533(unsigned char *p
, unsigned int block
, unsigned int len
, int eof
)
1033 static unsigned char *extdata
= NULL
, *extend
= NULL
;
1034 unsigned char *extpath
= NULL
;
1035 unsigned char *endp
;
1038 end_of_rfc1533
= NULL
;
1039 if (memcmp(p
, rfc1533_cookie
, sizeof(rfc1533_cookie
)))
1040 return(0); /* no RFC 1533 header found */
1045 if (memcmp(p
, rfc1533_cookie
, sizeof(rfc1533_cookie
)))
1046 return(0); /* no RFC 1533 header found */
1049 if (extend
+ len
<= (unsigned char *)
1050 rfc1533_venddata
+ sizeof(rfc1533_venddata
)) {
1051 memcpy(extend
, p
, len
);
1054 printf("Overflow in vendor data buffer! Aborting...\n");
1055 *extdata
= RFC1533_END
;
1058 p
= extdata
; endp
= extend
;
1063 unsigned char c
= *p
;
1064 if (c
== RFC1533_PAD
) {
1068 else if (c
== RFC1533_END
) {
1069 end_of_rfc1533
= endp
= p
;
1072 else if (c
== RFC1533_NETMASK
)
1073 memcpy(&netmask
, p
+2, sizeof(in_addr
));
1074 else if (c
== RFC1533_GATEWAY
) {
1075 /* This is a little simplistic, but it will
1076 usually be sufficient.
1077 Take only the first entry */
1078 if (TAG_LEN(p
) >= sizeof(in_addr
))
1079 memcpy(&arptable
[ARP_GATEWAY
].ipaddr
, p
+2, sizeof(in_addr
));
1081 else if (c
== RFC1533_EXTENSIONPATH
)
1083 else if (c
== RFC2132_MSG_TYPE
)
1085 else if (c
== RFC2132_SRV_ID
)
1086 memcpy(&dhcp_server
, p
+2, sizeof(in_addr
));
1087 else if (c
== RFC1533_HOSTNAME
) {
1089 hostnamelen
= *(p
+ 1);
1091 else if (c
== RFC1533_VENDOR_CONFIGFILE
){
1092 int l
= TAG_LEN (p
);
1094 /* Eliminate the trailing NULs according to RFC 2132. */
1095 while (*(p
+ 2 + l
- 1) == '\000' && l
> 0)
1098 /* XXX: Should check if LEN is less than the maximum length
1099 of CONFIG_FILE. This kind of robustness will be a goal
1101 memcpy (config_file
, p
+ 2, l
);
1103 vendor_configfile
= p
+ 2;
1104 vendor_configfile_len
= l
;
1105 configfile_origin
= CFG_150
;
1110 p
+= TAG_LEN(p
) + 2;
1112 extdata
= extend
= endp
;
1113 if (block
<= 0 && extpath
!= NULL
) {
1115 if (TAG_LEN(extpath
) >= sizeof(fname
)){
1116 printf("Overflow in vendor data buffer! Aborting...\n");
1117 *extdata
= RFC1533_END
;
1120 memcpy(fname
, extpath
+2, TAG_LEN(extpath
));
1121 fname
[(int)TAG_LEN(extpath
)] = '\0';
1122 printf("Loading BOOTP-extension file: %s\n",fname
);
1123 tftp_file_read(fname
, decode_rfc1533
);
1125 return 1; /* proceed with next block */
1129 /* FIXME double check TWO_SECOND_DIVISOR */
1130 #define TWO_SECOND_DIVISOR (RAND_MAX/TICKS_PER_SEC)
1131 /**************************************************************************
1132 RFC2131_SLEEP_INTERVAL - sleep for expotentially longer times (base << exp) +- 1 sec)
1133 **************************************************************************/
1134 long rfc2131_sleep_interval(long base
, int exp
)
1137 #ifdef BACKOFF_LIMIT
1138 if (exp
> BACKOFF_LIMIT
)
1139 exp
= BACKOFF_LIMIT
;
1141 tmo
= (base
<< exp
) + (TICKS_PER_SEC
- (random()/TWO_SECOND_DIVISOR
));
1145 #ifdef MULTICAST_LEVEL2
1146 /**************************************************************************
1147 RFC1112_SLEEP_INTERVAL - sleep for expotentially longer times, up to (base << exp)
1148 **************************************************************************/
1149 long rfc1112_sleep_interval(long base
, int exp
)
1151 unsigned long divisor
, tmo
;
1152 #ifdef BACKOFF_LIMIT
1153 if (exp
> BACKOFF_LIMIT
)
1154 exp
= BACKOFF_LIMIT
;
1156 divisor
= RAND_MAX
/(base
<< exp
);
1157 tmo
= random()/divisor
;
1160 #endif /* MULTICAST_LEVEL_2 */
1161 /* ifconfig - configure network interface. */
1163 ifconfig (char *ip
, char *sm
, char *gw
, char *svr
)
1169 if (! inet_aton (sm
, &tmp
))
1172 netmask
= tmp
.s_addr
;
1177 if (! inet_aton (ip
, &arptable
[ARP_CLIENT
].ipaddr
))
1180 if (! netmask
&& ! sm
)
1181 netmask
= default_netmask ();
1184 if (gw
&& ! inet_aton (gw
, &arptable
[ARP_GATEWAY
].ipaddr
))
1187 /* Clear out the ARP entry. */
1188 grub_memset (arptable
[ARP_GATEWAY
].node
, 0, ETH_ALEN
);
1190 if (svr
&& ! inet_aton (svr
, &arptable
[ARP_SERVER
].ipaddr
))
1194 grub_memset (arptable
[ARP_SERVER
].node
, 0, ETH_ALEN
);
1198 if (IP_BROADCAST
== (netmask
| arptable
[ARP_CLIENT
].ipaddr
.s_addr
)
1199 || netmask
== (netmask
| arptable
[ARP_CLIENT
].ipaddr
.s_addr
)
1206 update_network_configuration();
1211 * print_network_configuration
1213 * Output the network configuration. It may broke the graphic console now.:-(
1215 void print_network_configuration (void)
1217 EnterFunction("print_network_configuration");
1218 if (! network_ready
)
1219 grub_printf ("Network interface not initialized yet.\n");
1221 if (hostnamelen
== 0)
1222 etherboot_printf ("Hostname: not set\n");
1224 etherboot_printf ("Hostname: %s\n", hostname
);
1226 etherboot_printf ("Address: %@\n", arptable
[ARP_CLIENT
].ipaddr
.s_addr
);
1227 etherboot_printf ("Netmask: %@\n", netmask
);
1228 etherboot_printf ("Gateway: %@\n", arptable
[ARP_GATEWAY
].ipaddr
.s_addr
);
1229 etherboot_printf ("Server: %@\n", arptable
[ARP_SERVER
].ipaddr
.s_addr
);
1230 if (vendor_configfile
== NULL
) {
1231 etherboot_printf ("Site Option 150: not set\n");
1234 * vendor_configfile points into the packet and
1235 * is not NULL terminated, so it needs to be
1236 * patched up before printing it out
1238 char c
= vendor_configfile
[vendor_configfile_len
];
1239 vendor_configfile
[vendor_configfile_len
] = '\0';
1240 etherboot_printf ("Site Option 150: %s\n",
1242 vendor_configfile
[vendor_configfile_len
] = c
;
1245 if (bootfile
== NULL
)
1246 etherboot_printf ("BootFile: not set\n");
1248 etherboot_printf ("BootFile: %s\n", bootfile
);
1250 etherboot_printf ("GRUB menu file: %s", config_file
);
1251 switch (configfile_origin
) {
1253 etherboot_printf (" from hardcoded default\n");
1256 etherboot_printf (" from Site Option 150\n");
1259 etherboot_printf (" inferred from system MAC\n");
1262 etherboot_printf (" inferred from BootFile\n");
1265 etherboot_printf ("\n");
1268 LeaveFunction("print_network_configuration");
1272 * update_network_configuration
1274 * Update network configuration for diskless clients (Solaris only)
1276 static void update_network_configuration (void)
1278 #ifdef SOLARIS_NETBOOT
1279 struct sol_netinfo
{
1280 uint8_t sn_infotype
;
1284 unsigned long sn_ciaddr
;
1285 unsigned long sn_siaddr
;
1286 unsigned long sn_giaddr
;
1287 unsigned long sn_netmask
;
1288 uint8_t sn_macaddr
[1];
1291 if (! network_ready
)
1294 sip
= (struct sol_netinfo
*)dhcpack_buf
;
1295 sip
->sn_infotype
= 0xf0; /* something not BOOTP_REPLY */
1296 sip
->sn_mactype
= 4; /* DL_ETHER */
1297 sip
->sn_maclen
= ETH_ALEN
;
1298 sip
->sn_ciaddr
= arptable
[ARP_CLIENT
].ipaddr
.s_addr
;
1299 sip
->sn_siaddr
= arptable
[ARP_SERVER
].ipaddr
.s_addr
;
1300 sip
->sn_giaddr
= arptable
[ARP_GATEWAY
].ipaddr
.s_addr
;
1301 sip
->sn_netmask
= netmask
;
1302 memcpy(sip
->sn_macaddr
, arptable
[ARP_CLIENT
].node
, ETH_ALEN
);
1303 dhcpack_length
= sizeof (*sip
) + sip
->sn_maclen
- 1;
1304 #endif /* SOLARIS_NETBOOT */
1310 * Mark network unusable, and disable NICs
1312 void cleanup_net (void)
1315 /* Stop receiving packets. */
1324 /*******************************************************************
1325 * dhcp implementation reusing the BIOS pxe stack
1328 dhcp_copy(struct dhcp_t
*dhcpreply
)
1331 int ret
, len
= DHCP_OPT_LEN
;
1333 /* fill in netinfo */
1334 dhcpack_length
= sizeof (struct dhcp_t
);
1335 memcpy((char *)dhcpack_buf
, (char *)dhcpreply
, dhcpack_length
);
1337 memcpy(arptable
[ARP_CLIENT
].node
, dhcpreply
->bp_hwaddr
, ETH_ALEN
);
1338 arptable
[ARP_CLIENT
].ipaddr
.s_addr
= dhcpreply
->bp_yiaddr
.s_addr
;
1339 dhcp_addr
.s_addr
= dhcpreply
->bp_yiaddr
.s_addr
;
1340 netmask
= default_netmask();
1341 arptable
[ARP_SERVER
].ipaddr
.s_addr
= dhcpreply
->bp_siaddr
.s_addr
;
1342 memset(arptable
[ARP_SERVER
].node
, 0, ETH_ALEN
); /* Kill arp */
1343 arptable
[ARP_GATEWAY
].ipaddr
.s_addr
= dhcpreply
->bp_giaddr
.s_addr
;
1344 memset(arptable
[ARP_GATEWAY
].node
, 0, ETH_ALEN
); /* Kill arp */
1345 bootfile
= dhcpreply
->bp_file
;
1346 memcpy((char *)rfc1533_venddata
, (char *)(dhcpreply
->bp_vend
), len
);
1347 decode_rfc1533(rfc1533_venddata
, 0, len
, 1);
1352 struct dhcp_t
*dhcpreply
;
1354 if (!undi_bios_pxe((void **)&dhcpreply
))
1357 dhcp_copy(dhcpreply
);