xref: /illumos-gate/usr/src/man/man4p/ndp.4p (revision 9b9d39d2a32ff806d2431dbcc50968ef1e6d46b2)
1.\"
2.\" This file and its contents are supplied under the terms of the
3.\" Common Development and Distribution License ("CDDL"), version 1.0.
4.\" You may only use this file in accordance with the terms of version
5.\" 1.0 of the CDDL.
6.\"
7.\" A full copy of the text of the CDDL should have accompanied this
8.\" source.  A copy of the CDDL is also available via the Internet at
9.\" http://www.illumos.org/license/CDDL.
10.\"
11.\"
12.\" Copyright (c) 2015, Joyent, Inc.  All rights reserved.
13.\"
14.Dd December 2, 2023
15.Dt NDP 4P
16.Os
17.Sh NAME
18.Nm ndp ,
19.Nm NDP
20.Nd Neighbor Discovery Protocol
21.Sh SYNOPSIS
22.In sys/socket.h
23.In sys/sockio.h
24.In netinet/in.h
25.In net/if.h
26.Bd -literal
27s = socket(PF_INET6, SOCK_DGRAM, 0);
28
29struct lifreq lifr;
30ioctl(s, SIOCLIFGETND, &lifr);
31ioctl(s, SIOCLIFSETND, &lifr);
32ioctl(s, SIOCLIFDELND, &lifr);
33.Ed
34.Sh DESCRIPTION
35The Neighbor Discovery Protocol (NDP) is a protocol used to distribute and
36request information about neighboring IPv6 systems on the local network, much
37like
38.Xr ARP 4P
39for IPv4.
40NDP is also responsible for spreading information about the network gateway and
41how hosts should configure themselves
42.Pq see Xr in.ndpd 8 for more on how this happens .
43.Sh APPLICATION PROGRAMMING INTERFACE
44The operating system provides several ioctls to help manipulate the mappings
45obtained through NDP.
46They are
47.Sy SIOCLIFGETND ,
48.Sy SIOCLIFSETND ,
49and
50.Sy SIOCLIFDELND ,
51for getting, setting, and deleting respectively.
52Each of these ioctls takes a
53.Vt struct lifreq
54.Pq see Xr if 4P for details ,
55where the
56.Fa lifr_lifru
57field is of type
58.Vt struct lif_nd_req :
59.Bd -literal -offset 2m
60typedef struct lif_nd_req {
61        struct sockaddr_storage lnr_addr;
62        uint8_t                 lnr_state_create;
63        uint8_t                 lnr_state_same_lla;
64        uint8_t                 lnr_state_diff_lla;
65        int                     lnr_hdw_len;
66        int                     lnr_flags;
67        int                     lnr_pad0;
68        char                    lnr_hdw_addr[ND_MAX_HDW_LEN];
69} lif_nd_req_t;
70.Ed
71.Pp
72The
73.Fa lnr_addr
74field should be filled in with an IPv6 address
75.Pq see Xr sockaddr_in6 3SOCKET ,
76and the
77.Fa lnr_hdw_addr
78is the link-layer address of length
79.Fa lnr_hdw_len .
80.Pp
81State flags for
82.Fa lnr_state_create ,
83.Fa lnr_state_same_lla ,
84and
85.Fa lnr_state_diff_lla
86can be set to one of the following values:
87.Bl -tag -offset indent -width 16m
88.It Sy ND_UNCHANGED
89For ioctls that don't modify state
90.It Sy ND_INCOMPLETE
91Address resolution is currently in progress
92.It Sy ND_REACHABLE
93The link-layer address has recently been reachable
94.It Sy ND_STALE
95The link-layer address may be unreachable, and the system shouldn't do anything
96.It Sy ND_DELAY
97This entry hasn't yet started sending Neighbor Solicitations
98.It Sy ND_PROBE
99The operating system is currently sending out Neighbor Solicitations for the address
100.It Sy ND_UNREACHABLE
101The link-layer address is unreachable, and this entry is going to be deleted.
102.El
103.sp
104When creating a new entry, the only valid values for
105.Fa lnr_state_create
106are
107.Sy ND_REACHABLE
108and
109.Sy ND_STALE .
110Any other value will return
111.Sy EINVAL .
112The
113.Fa lnr_state_same_lla
114and
115.Fa lnr_state_diff_lla
116fields are reserved for future use and can be safely set to
117.Sy ND_UNCHANGED
118and
119.Sy ND_STALE
120respectively.
121.Pp
122Flags that can be placed in
123.Fa lnr_flags
124are:
125.Bl -tag -offset indent -width 16m
126.It Sy NDF_ISROUTER_ON
127Mark this entry as being a router.
128This will cause Neighbor Advertisements for this address to be sent with the
129R-bit (Router).
130.It Sy NDF_ISROUTER_OFF
131If this entry was flagged as being a router, remove the flag.
132.It Sy NDF_ANYCAST_ON
133Mark this entry as being for an anycast address.
134This prevents sending Neighbor Advertisements with the O-bit (Override).
135.It Sy NDF_ANYCAST_OFF
136If this entry was flagged as an anycast address, remove the flag.
137.It Sy NDF_STATIC
138Prevent this entry from being deleted by the system.
139.El
140.sp
141When using
142.Sy SIOCLIFGETND ,
143these flags represent the current state of the corresponding Neighbor Cache
144Entry.
145When using
146.Sy SIOCLIFSETND ,
147these flags represent what changes should be applied to the underlying entry.
148.Pp
149The only fields that need to be set for the
150.Sy SIOCLIFGETND
151or
152.Sy SIOCLIFDELND
153ioctls are
154.Fa lifr_name
155and
156.Fa lnr_addr .
157All other fields should be zeroed out.
158After successfully getting an entry, the other fields will be filled in.
159When using
160.Sy SIOCLIFSETND ,
161all fields should be set to an appropriate value, as described above, with the
162exception of
163.Fa lnr_pad0 ,
164which is unused and only exists for padding purposes.
165.Pp
166After performing the ioctl, the following errors may be returned through the
167global
168.Sy errno
169variable:
170.Bl -tag -offset indent -width 16m
171.It Sy EAFNOSUPPORT
172A non-IPv6 socket was used to perform the ioctl.
173.It Sy EINVAL
174The request contents were bad.
175This could be because conflicting flags were used, the specified interface
176wasn't logical unit zero, or another reason.
177.It Sy ENOMEM
178The system ran out of memory for internal data structures.
179.It Sy ENXIO
180The specified interface does not exist.
181.It Sy EPERM
182The caller does not have permission to modify the Neighbor Cache Entries
183associated with this interface.
184They may be lacking the
185.Sy PRIV_SYS_NET_CONFIG
186privilege
187.Po see Xr privileges 7 Pc ,
188or the interface is managed by IPMP (IP Network Multipathing).
189.It Sy ESRCH
190There is no entry matching the specified address.
191.El
192.Sh EXAMPLES
193The following examples demonstrate how to get and set NDP mappings using the
194provided ioctls.
195They can be compiled by using a C compiler and linking against the sockets
196library.
197.Ss Example 1: Getting a mapping
198.Bd -literal -offset indent
199$ gcc -Wall -lsocket -o get get.c
200$ cat get.c
201/*
202 * Example of getting a mapping for a node name.
203 */
204#include <strings.h>
205#include <stdio.h>
206#include <stdlib.h>
207#include <sys/socket.h>
208#include <sys/sockio.h>
209#include <unistd.h>
210#include <netdb.h>
211#include <net/if.h>
212
213int get(char *host) {
214	struct lifreq lifr;
215	struct addrinfo hints, *serverinfo, *p;
216	int err, s;
217
218	bzero(&hints, sizeof (struct addrinfo));
219	hints.ai_family = PF_INET6;
220	hints.ai_protocol = IPPROTO_IPV6;
221
222	if ((err = getaddrinfo(host, NULL, &hints, &serverinfo)) != 0) {
223		(void) fprintf(stderr, "Unable to lookup %s: %s\en", host,
224		    gai_strerror(err));
225		return (1);
226	}
227
228	s = socket(AF_INET6, SOCK_DGRAM, 0);
229	if (s < 0) {
230		perror("Failed to open IPv6 socket");
231		return (1);
232	}
233
234	for (p = serverinfo; p != NULL; p = p->ai_next) {
235		/* Zero out structure */
236		bzero(&lifr, sizeof (struct lifreq));
237		(void) strlcpy(lifr.lifr_name, "net0",
238		    sizeof (lifr.lifr_name));
239		(void) memcpy(&lifr.lifr_nd.lnr_addr, p->ai_addr,
240		    sizeof (struct sockaddr_storage));
241
242		/* Get mapping */
243		if (ioctl(s, SIOCLIFGETND, &lifr) < 0) {
244			perror("Unable to get NDP mapping");
245			continue;
246		}
247
248		/*
249		 * lifr.lifr_nd.lnr_hdw_addr now contains the MAC address,
250		 * and can be used as desired.
251		 */
252	}
253
254	/*
255	 * Clean up linked list.
256	 */
257	freeaddrinfo(serverinfo);
258	return (0);
259}
260
261int main(int argc, char *argv[]) {
262	if (argc < 2)
263		exit(1);
264	return (get(argv[1]));
265}
266.Ed
267.sp
268Deleting a mapping would work similarly, except that instead of using
269.Sy SIOCLIFGETND ,
270you would instead use the
271.Sy SIOCLIFDELND
272ioctl.
273.Ss Example 2: Adding a mapping
274.Bd -literal -offset indent
275$ gcc -Wall -lsocket -o set set.c
276$ cat set.c
277/*
278 * Example of setting a mapping to an all-zero Ethernet address.
279 */
280#include <strings.h>
281#include <stdio.h>
282#include <stdlib.h>
283#include <sys/socket.h>
284#include <sys/sockio.h>
285#include <unistd.h>
286#include <netdb.h>
287#include <net/if.h>
288
289int set(char *host) {
290	struct lifreq lifr;
291	struct addrinfo hints, *serverinfo, *p;
292	int err, s;
293
294	bzero(&hints, sizeof (struct addrinfo));
295	hints.ai_family = PF_INET6;
296	hints.ai_protocol = IPPROTO_IPV6;
297
298	if ((err = getaddrinfo(host, NULL, &hints, &serverinfo)) != 0) {
299		(void) fprintf(stderr, "Unable to lookup %s: %s\en", host,
300		    gai_strerror(err));
301		return (1);
302	}
303
304	s = socket(AF_INET6, SOCK_DGRAM, 0);
305	if (s < 0) {
306		perror("Failed to open IPv6 socket");
307		return (1);
308	}
309
310	for (p = serverinfo; p != NULL; p = p->ai_next) {
311		/* Zero out structure */
312		bzero(&lifr, sizeof (struct lifreq));
313		(void) strlcpy(lifr.lifr_name, "net0",
314		    sizeof (lifr.lifr_name));
315		(void) memcpy(&lifr.lifr_nd.lnr_addr, p->ai_addr,
316		    sizeof (struct sockaddr_storage));
317
318		lifr.lifr_nd.lnr_state_create = ND_REACHABLE;
319		lifr.lifr_nd.lnr_flags = NDF_STATIC;
320
321		/* Get mapping */
322		if (ioctl(s, SIOCLIFSETND, &lifr) < 0) {
323			perror("Unable to set NDP mapping");
324			continue;
325		}
326	}
327
328	/*
329	 * Clean up linked list.
330	 */
331	freeaddrinfo(serverinfo);
332	return (0);
333}
334
335int main(int argc, char *argv[]) {
336	if (argc < 2)
337		exit(1);
338	return (set(argv[1]));
339}
340.Ed
341.Sh SEE ALSO
342.Xr sockaddr_in6 3SOCKET ,
343.Xr privileges 7 ,
344.Xr ifconfig 8 ,
345.Xr in.ndpd 8 ,
346.Xr ndp 8
347.Rs
348.%A Narten, T.
349.%A Nordmark, E.
350.%A Simpson, W.
351.%A Soliman, H.
352.%R Neighbor Discovery for IP version 6
353.%T RFC 4861
354.%D September 2007
355.Re
356