11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ciconst common = require('../common');
31cb0ef41Sopenharmony_ciif (!common.hasIPv6)
41cb0ef41Sopenharmony_ci  common.skip('no IPv6 support');
51cb0ef41Sopenharmony_ci
61cb0ef41Sopenharmony_ciconst assert = require('assert');
71cb0ef41Sopenharmony_ciconst dgram = require('dgram');
81cb0ef41Sopenharmony_ciconst os = require('os');
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ciconst { isWindows } = common;
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_cifunction linklocal() {
131cb0ef41Sopenharmony_ci  for (const [ifname, entries] of Object.entries(os.networkInterfaces())) {
141cb0ef41Sopenharmony_ci    for (const { address, family, scopeid } of entries) {
151cb0ef41Sopenharmony_ci      if (family === 'IPv6' && address.startsWith('fe80:')) {
161cb0ef41Sopenharmony_ci        return { address, ifname, scopeid };
171cb0ef41Sopenharmony_ci      }
181cb0ef41Sopenharmony_ci    }
191cb0ef41Sopenharmony_ci  }
201cb0ef41Sopenharmony_ci}
211cb0ef41Sopenharmony_ciconst iface = linklocal();
221cb0ef41Sopenharmony_ci
231cb0ef41Sopenharmony_ciif (!iface)
241cb0ef41Sopenharmony_ci  common.skip('cannot find any IPv6 interfaces with a link local address');
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_ciconst address = isWindows ? iface.address : `${iface.address}%${iface.ifname}`;
271cb0ef41Sopenharmony_ciconst message = 'Hello, local world!';
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ci// Create a client socket for sending to the link-local address.
301cb0ef41Sopenharmony_ciconst client = dgram.createSocket('udp6');
311cb0ef41Sopenharmony_ci
321cb0ef41Sopenharmony_ci// Create the server socket listening on the link-local address.
331cb0ef41Sopenharmony_ciconst server = dgram.createSocket('udp6');
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ciserver.on('listening', common.mustCall(() => {
361cb0ef41Sopenharmony_ci  const port = server.address().port;
371cb0ef41Sopenharmony_ci  client.send(message, 0, message.length, port, address);
381cb0ef41Sopenharmony_ci}));
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ciserver.on('message', common.mustCall((buf, info) => {
411cb0ef41Sopenharmony_ci  const received = buf.toString();
421cb0ef41Sopenharmony_ci  assert.strictEqual(received, message);
431cb0ef41Sopenharmony_ci  // Check that the sender address is the one bound,
441cb0ef41Sopenharmony_ci  // including the link local scope identifier.
451cb0ef41Sopenharmony_ci  assert.strictEqual(
461cb0ef41Sopenharmony_ci    info.address,
471cb0ef41Sopenharmony_ci    isWindows ? `${iface.address}%${iface.scopeid}` : address
481cb0ef41Sopenharmony_ci  );
491cb0ef41Sopenharmony_ci  server.close();
501cb0ef41Sopenharmony_ci  client.close();
511cb0ef41Sopenharmony_ci}, 1));
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ciserver.bind({ address });
54