1 #ifndef _IPXE_NDP_H
2 #define _IPXE_NDP_H
3 
4 /** @file
5  *
6  * Neighbour discovery protocol
7  *
8  */
9 
10 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
11 
12 #include <stdint.h>
13 #include <ipxe/in.h>
14 #include <ipxe/ipv6.h>
15 #include <ipxe/icmpv6.h>
16 #include <ipxe/neighbour.h>
17 
18 /** An NDP option header */
19 struct ndp_option_header {
20 	/** Type */
21 	uint8_t type;
22 	/** Length (in blocks of 8 bytes) */
23 	uint8_t blocks;
24 } __attribute__ (( packed ));
25 
26 /** NDP option block size */
27 #define NDP_OPTION_BLKSZ 8U
28 
29 /** NDP source link-layer address option */
30 #define NDP_OPT_LL_SOURCE 1
31 
32 /** NDP target link-layer address option */
33 #define NDP_OPT_LL_TARGET 2
34 
35 /** NDP source or target link-layer address option */
36 struct ndp_ll_addr_option {
37 	/** NDP option header */
38 	struct ndp_option_header header;
39 	/** Link-layer address */
40 	uint8_t ll_addr[0];
41 } __attribute__ (( packed ));
42 
43 /** NDP prefix information option */
44 #define NDP_OPT_PREFIX 3
45 
46 /** NDP prefix information */
47 struct ndp_prefix_information_option {
48 	/** NDP option header */
49 	struct ndp_option_header header;
50 	/** Prefix length */
51 	uint8_t prefix_len;
52 	/** Flags */
53 	uint8_t flags;
54 	/** Valid lifetime */
55 	uint32_t valid;
56 	/** Preferred lifetime */
57 	uint32_t preferred;
58 	/** Reserved */
59 	uint32_t reserved;
60 	/** Prefix */
61 	struct in6_addr prefix;
62 } __attribute__ (( packed ));
63 
64 /** NDP on-link flag */
65 #define NDP_PREFIX_ON_LINK 0x80
66 
67 /** NDP autonomous address configuration flag */
68 #define NDP_PREFIX_AUTONOMOUS 0x40
69 
70 /** NDP recursive DNS server option */
71 #define NDP_OPT_RDNSS 25
72 
73 /** NDP recursive DNS server */
74 struct ndp_rdnss_option {
75 	/** NDP option header */
76 	struct ndp_option_header header;
77 	/** Reserved */
78 	uint16_t reserved;
79 	/** Lifetime */
80 	uint32_t lifetime;
81 	/** Addresses */
82 	struct in6_addr addresses[0];
83 } __attribute__ (( packed ));
84 
85 /** NDP DNS search list option */
86 #define NDP_OPT_DNSSL 31
87 
88 /** NDP DNS search list */
89 struct ndp_dnssl_option {
90 	/** NDP option header */
91 	struct ndp_option_header header;
92 	/** Reserved */
93 	uint16_t reserved;
94 	/** Lifetime */
95 	uint32_t lifetime;
96 	/** Domain names */
97 	uint8_t names[0];
98 } __attribute__ (( packed ));
99 
100 /** An NDP option */
101 union ndp_option {
102 	/** Option header */
103 	struct ndp_option_header header;
104 	/** Source or target link-layer address option */
105 	struct ndp_ll_addr_option ll_addr;
106 	/** Prefix information option */
107 	struct ndp_prefix_information_option prefix;
108 	/** Recursive DNS server option */
109 	struct ndp_rdnss_option rdnss;
110 	/** DNS search list option */
111 	struct ndp_dnssl_option dnssl;
112 } __attribute__ (( packed ));
113 
114 /** An NDP neighbour solicitation or advertisement header */
115 struct ndp_neighbour_header {
116 	/** ICMPv6 header */
117 	struct icmp_header icmp;
118 	/** Flags */
119 	uint8_t flags;
120 	/** Reserved */
121 	uint8_t reserved[3];
122 	/** Target address */
123 	struct in6_addr target;
124 	/** Options */
125 	union ndp_option option[0];
126 } __attribute__ (( packed ));
127 
128 /** NDP router flag */
129 #define NDP_NEIGHBOUR_ROUTER 0x80
130 
131 /** NDP solicited flag */
132 #define NDP_NEIGHBOUR_SOLICITED 0x40
133 
134 /** NDP override flag */
135 #define NDP_NEIGHBOUR_OVERRIDE 0x20
136 
137 /** An NDP router advertisement header */
138 struct ndp_router_advertisement_header {
139 	/** ICMPv6 header */
140 	struct icmp_header icmp;
141 	/** Current hop limit */
142 	uint8_t hop_limit;
143 	/** Flags */
144 	uint8_t flags;
145 	/** Router lifetime */
146 	uint16_t lifetime;
147 	/** Reachable time */
148 	uint32_t reachable;
149 	/** Retransmission timer */
150 	uint32_t retransmit;
151 	/** Options */
152 	union ndp_option option[0];
153 } __attribute__ (( packed ));
154 
155 /** NDP managed address configuration */
156 #define NDP_ROUTER_MANAGED 0x80
157 
158 /** NDP other configuration */
159 #define NDP_ROUTER_OTHER 0x40
160 
161 /** An NDP router solicitation header */
162 struct ndp_router_solicitation_header {
163 	/** ICMPv6 header */
164 	struct icmp_header icmp;
165 	/** Reserved */
166 	uint32_t reserved;
167 	/** Options */
168 	union ndp_option option[0];
169 } __attribute__ (( packed ));
170 
171 /** An NDP header */
172 union ndp_header {
173 	/** ICMPv6 header */
174 	struct icmp_header icmp;
175 	/** Neighbour solicitation or advertisement header */
176 	struct ndp_neighbour_header neigh;
177 	/** Router solicitation header */
178 	struct ndp_router_solicitation_header rsol;
179 	/** Router advertisement header */
180 	struct ndp_router_advertisement_header radv;
181 } __attribute__ (( packed ));
182 
183 extern struct neighbour_discovery ndp_discovery;
184 
185 /**
186  * Transmit packet, determining link-layer address via NDP
187  *
188  * @v iobuf		I/O buffer
189  * @v netdev		Network device
190  * @v net_dest		Destination network-layer address
191  * @v net_source	Source network-layer address
192  * @v ll_source		Source link-layer address
193  * @ret rc		Return status code
194  */
ndp_tx(struct io_buffer * iobuf,struct net_device * netdev,const void * net_dest,const void * net_source,const void * ll_source)195 static inline int ndp_tx ( struct io_buffer *iobuf, struct net_device *netdev,
196 			   const void *net_dest, const void *net_source,
197 			   const void *ll_source ) {
198 
199 	return neighbour_tx ( iobuf, netdev, &ipv6_protocol, net_dest,
200 			      &ndp_discovery, net_source, ll_source );
201 }
202 
203 /** NDP settings block name */
204 #define NDP_SETTINGS_NAME "ndp"
205 
206 #endif /* _IPXE_NDP_H */
207