summaryrefslogtreecommitdiff
path: root/usr/src/man/man4p/ndp.4p
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/man/man4p/ndp.4p')
-rw-r--r--usr/src/man/man4p/ndp.4p355
1 files changed, 355 insertions, 0 deletions
diff --git a/usr/src/man/man4p/ndp.4p b/usr/src/man/man4p/ndp.4p
new file mode 100644
index 0000000000..06e1444512
--- /dev/null
+++ b/usr/src/man/man4p/ndp.4p
@@ -0,0 +1,355 @@
+.\"
+.\" This file and its contents are supplied under the terms of the
+.\" Common Development and Distribution License ("CDDL"), version 1.0.
+.\" You may only use this file in accordance with the terms of version
+.\" 1.0 of the CDDL.
+.\"
+.\" A full copy of the text of the CDDL should have accompanied this
+.\" source. A copy of the CDDL is also available via the Internet at
+.\" http://www.illumos.org/license/CDDL.
+.\"
+.\"
+.\" Copyright (c) 2015, Joyent, Inc. All rights reserved.
+.\"
+.Dd Sep 02, 2015
+.Dt NDP 4P
+.Os
+.Sh NAME
+.Nm ndp ,
+.Nm NDP
+.Nd Neighbor Discovery Protocol
+.Sh SYNOPSIS
+.In sys/socket.h
+.In sys/sockio.h
+.In netinet/in.h
+.In net/if.h
+.Bd -literal
+s = socket(PF_INET6, SOCK_DGRAM, 0);
+
+struct lifreq lifr;
+ioctl(s, SIOCLIFGETND, &lifr);
+ioctl(s, SIOCLIFSETND, &lifr);
+ioctl(s, SIOCLIFDELND, &lifr);
+.Ed
+.Sh DESCRIPTION
+The Neighbor Discovery Protocol (NDP) is a protocol used to distribute and
+request information about neighboring IPv6 systems on the local network, much
+like
+.Xr ARP 4P
+for IPv4.
+NDP is also responsible for spreading information about the network gateway and
+how hosts should configure themselves
+.Pq see Xr in.ndpd 8 for more on how this happens .
+.Sh APPLICATION PROGRAMMING INTERFACE
+The operating system provides several ioctls to help manipulate the mappings
+obtained through NDP.
+They are
+.Sy SIOCLIFGETND ,
+.Sy SIOCLIFSETND ,
+and
+.Sy SIOCLIFDELND ,
+for getting, setting, and deleting respectively.
+Each of these ioctls takes a
+.Vt struct lifreq
+.Pq see Xr if 4P for details ,
+where the
+.Fa lifr_lifru
+field is of type
+.Vt struct lif_nd_req :
+.Bd -literal -offset 2m
+typedef struct lif_nd_req {
+ struct sockaddr_storage lnr_addr;
+ uint8_t lnr_state_create;
+ uint8_t lnr_state_same_lla;
+ uint8_t lnr_state_diff_lla;
+ int lnr_hdw_len;
+ int lnr_flags;
+ int lnr_pad0;
+ char lnr_hdw_addr[ND_MAX_HDW_LEN];
+} lif_nd_req_t;
+.Ed
+.Pp
+The
+.Fa lnr_addr
+field should be filled in with an IPv6 address
+.Pq see Xr sockaddr_in6 3SOCKET ,
+and the
+.Fa lnr_hdw_addr
+is the link-layer address of length
+.Fa lnr_hdw_len .
+.Pp
+State flags for
+.Fa lnr_state_create ,
+.Fa lnr_state_same_lla ,
+and
+.Fa lnr_state_diff_lla
+can be set to one of the following values:
+.Bl -tag -offset indent -width 16m
+.It Sy ND_UNCHANGED
+For ioctls that don't modify state
+.It Sy ND_INCOMPLETE
+Address resolution is currently in progress
+.It Sy ND_REACHABLE
+The link-layer address has recently been reachable
+.It Sy ND_STALE
+The link-layer address may be unreachable, and the system shouldn't do anything
+.It Sy ND_DELAY
+This entry hasn't yet started sending Neighbor Solicitations
+.It Sy ND_PROBE
+The operating system is currently sending out Neighbor Solicitations for the address
+.It Sy ND_UNREACHABLE
+The link-layer address is unreachable, and this entry is going to be deleted.
+.El
+.sp
+When creating a new entry, the only valid values for
+.Fa lnr_state_create
+are
+.Sy ND_REACHABLE
+and
+.Sy ND_STALE .
+Any other value will return
+.Sy EINVAL .
+The
+.Fa lnr_state_same_lla
+and
+.Fa lnr_state_diff_lla
+fields are reserved for future use and can be safely set to
+.Sy ND_UNCHANGED
+and
+.Sy ND_STALE
+respectively.
+.Pp
+Flags that can be placed in
+.Fa lnr_flags
+are:
+.Bl -tag -offset indent -width 16m
+.It Sy NDF_ISROUTER_ON
+Mark this entry as being a router.
+This will cause Neighbor Advertisements for this address to be sent with the
+R-bit (Router).
+.It Sy NDF_ISROUTER_OFF
+If this entry was flagged as being a router, remove the flag.
+.It Sy NDF_ANYCAST_ON
+Mark this entry as being for an anycast address.
+This prevents sending Neighbor Advertisements with the O-bit (Override).
+.It Sy NDF_ANYCAST_OFF
+If this entry was flagged as an anycast address, remove the flag.
+.It Sy NDF_STATIC
+Prevent this entry from being deleted by the system.
+.El
+.sp
+When using
+.Sy SIOCLIFGETND ,
+these flags represent the current state of the corresponding Neighbor Cache
+Entry.
+When using
+.Sy SIOCLIFSETND ,
+these flags represent what changes should be applied to the underlying entry.
+.Pp
+The only fields that need to be set for the
+.Sy SIOCLIFGETND
+or
+.Sy SIOCLIFDELND
+ioctls are
+.Fa lifr_name
+and
+.Fa lnr_addr .
+All other fields should be zeroed out.
+After successfully getting an entry, the other fields will be filled in.
+When using
+.Sy SIOCLIFSETND ,
+all fields should be set to an appropriate value, as described above, with the
+exception of
+.Fa lnr_pad0 ,
+which is unused and only exists for padding purposes.
+.Pp
+After performing the ioctl, the following errors may be returned through the
+global
+.Sy errno
+variable:
+.Bl -tag -offset indent -width 16m
+.It Sy EAFNOSUPPORT
+A non-IPv6 socket was used to perform the ioctl.
+.It Sy EINVAL
+The request contents were bad.
+This could be because conflicting flags were used, the specified interface
+wasn't logical unit zero, or another reason.
+.It Sy ENOMEM
+The system ran out of memory for internal data structures.
+.It Sy ENXIO
+The specified interface does not exist.
+.It Sy EPERM
+The caller does not have permission to modify the Neighbor Cache Entries
+associated with this interface.
+They may be lacking the
+.Sy PRIV_SYS_NET_CONFIG
+privilege
+.Po see Xr privileges 7 Pc ,
+or the interface is managed by IPMP (IP Network Multipathing).
+.It Sy ESRCH
+There is no entry matching the specified address.
+.El
+.Sh EXAMPLES
+The following examples demonstrate how to get and set NDP mappings using the
+provided ioctls.
+They can be compiled by using a C compiler and linking against the sockets
+library.
+.Ss Example 1: Getting a mapping
+.Bd -literal -offset indent
+$ gcc -Wall -lsocket -o get get.c
+$ cat get.c
+/*
+ * Example of getting a mapping for a node name.
+ */
+#include <strings.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <net/if.h>
+
+int get(char *host) {
+ struct lifreq lifr;
+ struct addrinfo hints, *serverinfo, *p;
+ int err, s;
+
+ bzero(&hints, sizeof (struct addrinfo));
+ hints.ai_family = PF_INET6;
+ hints.ai_protocol = IPPROTO_IPV6;
+
+ if ((err = getaddrinfo(host, NULL, &hints, &serverinfo)) != 0) {
+ (void) fprintf(stderr, "Unable to lookup %s: %s\\n", host,
+ gai_strerror(err));
+ return (1);
+ }
+
+ s = socket(AF_INET6, SOCK_DGRAM, 0);
+ if (s < 0) {
+ perror("Failed to open IPv6 socket");
+ return (1);
+ }
+
+ for (p = serverinfo; p != NULL; p = p->ai_next) {
+ /* Zero out structure */
+ bzero(&lifr, sizeof (struct lifreq));
+ (void) strlcpy(lifr.lifr_name, "net0",
+ sizeof (lifr.lifr_name));
+ (void) memcpy(&lifr.lifr_nd.lnr_addr, p->ai_addr,
+ sizeof (struct sockaddr_storage));
+
+ /* Get mapping */
+ if (ioctl(s, SIOCLIFGETND, &lifr) < 0) {
+ perror("Unable to get NDP mapping");
+ continue;
+ }
+
+ /*
+ * lifr.lifr_nd.lnr_hdw_addr now contains the MAC address,
+ * and can be used as desired.
+ */
+ }
+
+ /*
+ * Clean up linked list.
+ */
+ freeaddrinfo(serverinfo);
+ return (0);
+}
+
+int main(int argc, char *argv[]) {
+ if (argc < 2)
+ exit(1);
+ return (get(argv[1]));
+}
+.Ed
+.sp
+Deleting a mapping would work similarly, except that instead of using
+.Sy SIOCLIFGETND ,
+you would instead use the
+.Sy SIOCLIFDELND
+ioctl.
+.Ss Example 2: Adding a mapping
+.Bd -literal -offset indent
+$ gcc -Wall -lsocket -o set set.c
+$ cat set.c
+/*
+ * Example of setting a mapping to an all-zero Ethernet address.
+ */
+#include <strings.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <net/if.h>
+
+int set(char *host) {
+ struct lifreq lifr;
+ struct addrinfo hints, *serverinfo, *p;
+ int err, s;
+
+ bzero(&hints, sizeof (struct addrinfo));
+ hints.ai_family = PF_INET6;
+ hints.ai_protocol = IPPROTO_IPV6;
+
+ if ((err = getaddrinfo(host, NULL, &hints, &serverinfo)) != 0) {
+ (void) fprintf(stderr, "Unable to lookup %s: %s\\n", host,
+ gai_strerror(err));
+ return (1);
+ }
+
+ s = socket(AF_INET6, SOCK_DGRAM, 0);
+ if (s < 0) {
+ perror("Failed to open IPv6 socket");
+ return (1);
+ }
+
+ for (p = serverinfo; p != NULL; p = p->ai_next) {
+ /* Zero out structure */
+ bzero(&lifr, sizeof (struct lifreq));
+ (void) strlcpy(lifr.lifr_name, "net0",
+ sizeof (lifr.lifr_name));
+ (void) memcpy(&lifr.lifr_nd.lnr_addr, p->ai_addr,
+ sizeof (struct sockaddr_storage));
+
+ lifr.lifr_nd.lnr_state_create = ND_REACHABLE;
+ lifr.lifr_nd.lnr_flags = NDF_STATIC;
+
+ /* Get mapping */
+ if (ioctl(s, SIOCLIFSETND, &lifr) < 0) {
+ perror("Unable to set NDP mapping");
+ continue;
+ }
+ }
+
+ /*
+ * Clean up linked list.
+ */
+ freeaddrinfo(serverinfo);
+ return (0);
+}
+
+int main(int argc, char *argv[]) {
+ if (argc < 2)
+ exit(1);
+ return (set(argv[1]));
+}
+.Ed
+.Sh SEE ALSO
+.Xr sockaddr_in6 3SOCKET ,
+.Xr privileges 7 ,
+.Xr ifconfig 8 ,
+.Xr in.ndpd 8 ,
+.Xr ndp 8
+.Rs
+.%A Narten, T.
+.%A Nordmark, E.
+.%A Simpson, W.
+.%A Soliman, H.
+.%R Neighbor Discovery for IP version 6
+.%T RFC 4861
+.%D September 2007
+.Re