[j-nsp] dhcpv6 IA_PD syslogging

Aaron Gould aaron1 at gvtc.com
Fri Sep 27 12:46:32 EDT 2024


does anyone know how to see dhcpv6 relayed packets and events in Junos?  
(ACX5048)

I have IA_NA and IA_PD working, but I'd like to trace/debug and see what 
the dhcpv6 packets look like as they are sent to the relay server.  
basically i want to see the dhcpv6 options and all that since I need to 
enable various options and want to see before and after affects


-Aaron


On 7/17/2024 9:55 AM, Jan Bacher via juniper-nsp wrote:
> Jared, this is similar to what I use.  Devices using dhcp-relay and 
> that are directly connected to the ACX cannot even ping the gateway -- 
> let alone route out.
>
> If I configure 'no-snoop' on the ACX, routers behind the ACX work fine.
>
> Am I missing a forwarding-option or a routing-option or should this 
> just work?  I've not had this issue with the MX routers.
>
>
> On 7/10/24 11:32, Jared Mauch via juniper-nsp wrote:
>>     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 at puck.nether.net
>>>>> https://puck.nether.net/mailman/listinfo/juniper-nsp
>>>>
>>>> -- 
>>>> -Aaron
>>>>
>>>> _______________________________________________
>>>> juniper-nsp mailing list juniper-nsp at puck.nether.net
>>>> https://puck.nether.net/mailman/listinfo/juniper-nsp
>>>
>>> -- 
>>> Jared Mauch  | pgp key available via finger from jared at 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 at puck.nether.net
>>> https://puck.nether.net/mailman/listinfo/juniper-nsp
>>
>>
> _______________________________________________
> juniper-nsp mailing list juniper-nsp at puck.nether.net
> https://puck.nether.net/mailman/listinfo/juniper-nsp

-- 
-Aaron



More information about the juniper-nsp mailing list