Here's my Juniper config:
dhcp-relay { dhcpv6 { overrides { allow-snooped-clients; } relay-agent-option-79; group FTTHCustomersv6 { relay-agent-remote-id { use-option-82; } interface irb.100; interface irb.200; } relay-agent-interface-id { use-option-82; } relay-agent-remote-id { use-option-82; keep-incoming-remote-id; } server-group { FTTHCustomers6 { 2001:db8:db8:db8:db8:db8:db8:db8; } } active-server-group FTTHCustomers6; } forward-snooped-clients configured-interfaces; overrides { trust-option-82; bootp-support; replace-ip-source-with giaddr; } server-group { FTTHCustomers { 169.254.1.1; 169.254.2.2; } } active-server-group FTTHCustomers; group FTTHCustomers { overrides { trust-option-82; bootp-support; replace-ip-source-with giaddr; } interface xe-0/0/47.0; interface irb.100; interface irb.200; } } On Wed, Jul 10, 2024 at 12:21:02PM -0400, Jared Mauch via juniper-nsp wrote: > like this: > > subnet6 2001:db8:0003::/64 { > # agent.link-address > > pool6 { > range6 2001:db8:3::100 2001:db8:3::fff0; > } > option dhcp6.next-hop 2001:db8:0003::1; > prefix6 2001:db8:3:0010:: 2001:db8:3:ff00:: /60; > > > on commit { > set agent_circuit-id = concat("", v6relay(1, option > dhcp6.interface-id)); > log ( error, concat( "COMMIT6|Interface:", v6relay(1, option > dhcp6.interface-id), "|", v6relay(1, option dhcp6.relay-id), "|", v6relay(1, > option dhcp6.remote-id))); > log ( error, concat( "HWADDR-DUID: ", v6relay(1, > (binary-to-ascii(16, 8, ":", option dhcp6.client-linklayer-addr))), " is > connected to ", binary-to-ascii(16, 8, ":", option dhcp6.client-id))); > log (info, concat ("Lease6 for ", binary-to-ascii(16,16, ":", > substring(suffix(option dhcp6.ia-na, 24),0,16)), " lease to ",v6relay(1, > (binary-to-ascii(16, 8, ":", option dhcp6.client-linklayer-addr))))); > > if exists dhcp6.client-id { log(error, concat(" dhcp6.client-id > = ", binary-to-ascii(16, 8, ":", v6relay(1, option dhcp6.client-id)))); > log(error, concat(" dhcp6.ia-addr = ", binary-to-ascii(16, 16, > ":", v6relay(1, option dhcp6.ia-addr))));} > log(error, concat(" v6relay(1, dhcp6.interface-id) = ", > v6relay(1, option dhcp6.interface-id))); > log(error, concat(" v6relay(1, dhcp6.subscriber-id) = ", > v6relay(1, option dhcp6.subscriber-id))); > log(error, concat(" v6relay(1, dhcp6.relay-id) = ", v6relay(1, > option dhcp6.relay-id))); > # dhcp6.ia-prefix > log(error, concat(" v6relay(1, dhcp6.ia-prefix) = ", > binary-to-ascii(16, 16, ":", suffix(v6relay(1, option dhcp6.ia-prefix), 16)) > ) ); > log(error, concat(" dhcp6.ia-na = ", binary-to-ascii(16, 16, ":", > suffix(option dhcp6.ia-na, 16)) ) ); > log(error, concat(" dhcp6.ia-ta = ", option dhcp6.ia-ta)); > > log (error, concat (" v6RELAY1(dhcp6.client-linklayer-addr): ", > v6relay(1, (binary-to-ascii(16, 8, ":", option > dhcp6.client-linklayer-addr))))); > log (error, concat (" v6RELAY1(dhcp6.ia-addr): ", v6relay(1, > (binary-to-ascii(16, 16, ":", option dhcp6.ia-addr))))); > log (error, concat (" v6RELAY1(dhcp6.subscriber-id):", v6relay(1, > option dhcp6.subscriber-id))); > log (error, concat (" v6RELAY1(agent.circuit-id):", v6relay(1, > option agent.circuit-id))); > log (error, concat (" v6RELAY1(agent1.remote-id):", v6relay(1, > option agent.remote-id))); > log (error, concat (" dhcp6.remote-id:", option dhcp6.remote-id)); > log (error, concat (" v6RELAY1(dhcp6.ia-na):", > substring(suffix(v6relay(1, option dhcp6.ia-na), 24), 0, 16))); > log (info, concat (" hostname(domain-name):", option > domain-name)); > > log (error, concat ("--> Client-DUID: ", > binary-to-ascii(16, 8, ":", option dhcp6.client-id), > " | IP Address: ", > binary-to-ascii(16, 16, ":", substring(suffix(option > dhcp6.ia-na, 24), 0, 16)))); > > log (error, concat ("--> Client-DUID: ", > binary-to-ascii(16, 8, ":", option dhcp6.client-id), > " | Lease IPv6 ", > binary-to-ascii(16, 16, ":", substring(suffix(option > dhcp6.ia-na, 24), 0, 16)), > " | lease to ", > v6relay(1, (binary-to-ascii(16, 8, ":", option > dhcp6.client-linklayer-addr))), > " | PD Range: ", binary-to-ascii(16, 16, ":", suffix(option > dhcp6.ia-pd, 16)), > "/", > binary-to-ascii(10, 8, ":", substring(suffix(option > dhcp6.ia-pd, 17), 0, 1)), > " | MacID: ", binary-to-ascii(16, 8, ":", suffix(option > dhcp6.client-id, 6)), > " | Interface:", v6relay(1, option dhcp6.interface-id)) > ); > } > on release { > log(error, concat("RELEASE6 from", agent_circuit-id)); > } > > > On Wed, Jul 03, 2024 at 11:42:35AM -0500, Aaron Gould via juniper-nsp wrote: > > how are we supposed to deploy ipv6 without the ability to log who has what? > > > > -Aaron > > > > On 7/3/2024 10:10 AM, Gert Doering via juniper-nsp wrote: > > > Hi, > > > > > > On Wed, Jul 03, 2024 at 10:05:43AM -0500, Chris Adams via juniper-nsp > > > wrote: > > > > I haven't looked in a bit, but at one point Kea's built-in logging was > > > > pretty minimal, with "ISP level" logging done as a paid add-on module. > > > > They've got to pay the bills, but I dislike that model. > > > pay-for logging might suck, but it's way better than "can you open a > > > feature request that we'll subsequently ignore" logging... > > > > > > gert > > > > > > _______________________________________________ > > > juniper-nsp mailing list juniper-nsp@puck.nether.net > > > https://puck.nether.net/mailman/listinfo/juniper-nsp > > > > -- > > -Aaron > > > > _______________________________________________ > > juniper-nsp mailing list juniper-nsp@puck.nether.net > > https://puck.nether.net/mailman/listinfo/juniper-nsp > > -- > Jared Mauch | pgp key available via finger from ja...@puck.nether.net > clue++; | http://puck.nether.net/~jared/ My statements are only mine. > #!/usr/bin/python3 > > # (c) 2024 Jared Mauch > # > > from isc_dhcp_leases import Lease, IscDhcpLeases > > import binascii > > leases = IscDhcpLeases('/var/lib/dhcp/dhcpd6.leases') > #leases.get() # Returns the leases as a list of Lease objects > #leases.get_current() # Returns only the currently valid dhcp leases as dict > # The key of the dict is the device mac address and the > # Value is a Lease object > > olts = {} > olts['F09FC23F7ACC'] = 'olt1' > > duids = {} > duid_info_na = { } > duid_info_pd = { } > duid_info_v4 = { } > duid_info_hostname = { } > duid_info_cid = { } > duid_cid_mac = { } > duid_info_vendor = { } > > print("parsing leases6") > for lease in leases.get(): > # print(lease,vars(lease)) > > # parse last 6 bytes only > duidlen = len(lease.duid) > macloc = duidlen - 6 > # print("duid(len) =", len(lease.duid), macloc) > duid = ':'.join('{:02x}'.format(x) for x in lease.duid[-6:]) > # print("duid=", duid) > # duid_info_ip[duid] = lease.ip > duids[duid] = ':'.join('{:02x}'.format(x) for x in lease.duid) > # print("duid=", duid) > cid = lease.options.get('cid', None) > duid_info_cid[duid] = cid > if cid is not None: > duid_cid_mac[cid] = duid_cid_mac.get(cid, 0) + 1 > > # if duid_info_cid[duid] is not None: > # print(duid, duid_info_cid[duid]) > > if lease.type == 'na': > duid_info_na[duid] = lease.ip > # print("saving NA lease") > if lease.type == 'pd': > duid_info_pd[duid] = lease.ip > # print("saving PD lease") > # print(lease.ip, str(lease.type)) > > # print(lease,vars(lease)) > > > print("parsing leases4") > leases = IscDhcpLeases('/var/lib/dhcp/dhcpd.leases') > for lease in leases.get(): > if lease.binding_state in ('active'): > # print(lease,vars(lease)) > # mac_duid = "00:03:00:01:" + lease.ethernet > mac_duid = lease.ethernet > duids[mac_duid] = mac_duid > duid_info_v4[mac_duid] = lease.ip > cid = lease.options.get('agent.circuit-id', None) > duid_info_cid[mac_duid] = cid > if cid is not None: > duid_cid_mac[cid] = duid_cid_mac.get(cid, 0) + 1 > duid_info_vendor[mac_duid] = > lease.sets.get('vendor-class-identifier', '') > duid_info_hostname[mac_duid] = lease.hostname > # print('\t', lease.ip, lease.hostname, lease.ethernet, > lease.options.get('agent.circuit-id', ''), > lease.sets.get('vendor-class-identifier', '')) > > print("--- end parsing ---") > #print(duids) > for x in sorted(duids.keys()): > print("hwaddr: %s " % x) > if x not in duids[x]: > print("\tHWADDR NOT IN DUID: (%s,%s)" % (x, duids[x])) > if duid_info_hostname.get(x, None) is not None: > print("\thostname: %s" % duid_info_hostname.get(x)) > if duid_info_vendor.get(x, None) is not None: > print("\tvendor: %s" % duid_info_vendor.get(x)) > if duid_info_cid.get(x, None) is not None: > cid = duid_info_cid.get(x, None) > cid = cid[1:] # remove first quote > cid = cid[:-1] # remove last quote? > vals = cid.split('/') > olt = vals[0].upper() > # print(olt, olts.get(olt, None)) > # print(vals) > print("\tCID:\t(%s)%s\tnum_mac=%d" % (olts.get(olt, None), cid, > duid_cid_mac.get(duid_info_cid.get(x)))) > if duid_info_v4.get(x, None) is not None: > print("\tv4\t%s" % duid_info_v4.get(x)) > if duid_info_na.get(x, None) is not None: > print("\tNA\t%s" % duid_info_na.get(x)) > if duid_info_pd.get(x, None) is not None: > print("\tPD\t%s" % duid_info_pd.get(x)) > _______________________________________________ > juniper-nsp mailing list juniper-nsp@puck.nether.net > https://puck.nether.net/mailman/listinfo/juniper-nsp -- Jared Mauch | pgp key available via finger from ja...@puck.nether.net clue++; | http://puck.nether.net/~jared/ My statements are only mine. _______________________________________________ juniper-nsp mailing list juniper-nsp@puck.nether.net https://puck.nether.net/mailman/listinfo/juniper-nsp