Hah.  No worries; I'm just glad that I wasn't too terribly off-base.
:-)  I can be available for testing if needed.

Thanks!


--seth



On Fri, Apr 30, 2010 at 2:31 AM, Gilles Chehade <gil...@poolp.org> wrote:
> Hi Seth,
>
> It is a known issue, I actually had pulled the code for inet_net_pton()
> from NetBSD many months ago, when I first realized inet6 masks were not
> working in smtpd, but then I got sucked into other stuff and forgot it.
>
> I'll review the diff again ... :-)
>
> Thanks,
> Gilles
>
> On Fri, Apr 30, 2010 at 02:13:11AM -0400, Seth Wright wrote:
>> Okay, I'm officially stumped.  Can someone lend me a clue as to what,
>> if anything, I'm doing wrong in the following scenario?
>>
>> I was playing around with smtpd(8) configuration options the other
>> day, and tried to write an "accept" rule in smtpd.conf for an IPv6
>> subnet.  However, when I tried to verify the config I got an error:
>>
>>
>> s...@fw ~ $ grep 2001 /etc/mail/smtpd.conf
>> accept from 2001:470:8:1ee::/64 for all relay
>> s...@fw ~ $ smtpd -n
>> smtpd: inet_net_pton: Address family not supported by protocol family
>>
>>
>> I tracked down that error to /usr/src/usr.sbin/smtpd/parse.y, where in
>> a few places the code is passing AF_INET6 as the address family
>> argument to the function "inet_net_pton()" when it tries to parse the
>> address/subnet string as an IPv6 entity (seems logical to me).
>> However, in looking at /usr/src/lib/libc/net/inet_net_pton.c, that
>> function does not actually accept AF_INET6 as a valid address family:
>>
>>
>> int
>> inet_net_pton(int af, const char *src, void *dst, size_t size)
>> {
>>       switch (af) {
>>       case AF_INET:
>>               return (inet_net_pton_ipv4(src, dst, size));
>>       default:
>>               errno = EAFNOSUPPORT;
>>               return (-1);
>>       }
>> }
>>
>>
>> I looked around a bit and found that NetBSD does have code to handle
>> the AF_INET6 case, so I borrowed their code as a test (I guess it's
>> actually Paul Vixie's BIND code?), recompiled libc, and now 'smtpd -n'
>> says the configuration is OK.  Great...kind of.  I did have to change
>> the 'accept' rule above to add a zero at the end of the string in
>> order for it to pass inspection for whatever reason:
>>
>>
>> s...@bsd ~ $ grep 2001 /etc/mail/smtpd.conf
>> accept from 2001:470:8:1ee::/64 for all relay
>> s...@bsd ~ $ smtpd -n
>> smtpd: inet_net_pton: No such file or directory
>> [...]
>> s...@bsd ~ $ grep 2001 /etc/mail/smtpd.conf
>> accept from 2001:470:8:1ee::0/64 for all relay
>> s...@bsd ~ $ smtpd -n
>> configuration OK
>>
>>
>> Anyway, I started smtpd up again, did a quick test, and...it still failed:
>>
>>
>> s...@darwin ~ $ telnet bsd.crosse.org 25
>> Trying 2001:470:8:1ee:20c:29ff:fe18:1984...
>> Connected to bsd.crosse.org.
>> Escape character is '^]'.
>> 220 bsd.crosse.org ESMTP OpenSMTPD
>> helo darwin.crosse.org
>> 250 bsd.crosse.org Hello darwin.crosse.org
>> [IPv6:2001:470:8:1ee:5ab0:35ff:fe78:c7a0], pleased to meet you
>> mail from:<s...@darwin.crosse.org>
>> 250 2.1.0 Sender ok
>> rcpt to:<s...@crosse.org>
>> 530 5.0.0 Recipient rejected: s...@crosse.org
>> quit
>> 221 2.0.0 bsd.crosse.org Closing connection
>> Connection closed by foreign host.
>>
>>
>> The smtpd debug output for the session looks like this:
>>
>>
>> s...@bsd /usr/src/usr.sbin/smtpd $ sudo smtpd -dv
>> startup [debug mode]
>> parent_send_config: configuring smtp
>> parent_send_config_client_certs: configuring smtp
>> parent_send_config_ruleset: reloading rules and maps
>> parent_enqueue_offline: path /offline/1272603601.j459NrpVLg
>> smtp_setup_events: listen on IPv6:2001:470:8:1ee:20c:29ff:fe18:1984
>> port 25 flags 0x0 cert "vic0"
>> smtp_setup_events: listen on 192.168.2.24 port 25 flags 0x0 cert "vic0"
>> smtp_setup_events: listen on IPv6:fe80:1::20c:29ff:fe18:1984 port 25
>> flags 0x0 cert "vic0"
>> smtp_setup_events: listen on IPv6:fe80:3::1 port 25 flags 0x0 cert "lo0"
>> smtp_setup_events: listen on IPv6:::1 port 25 flags 0x0 cert "lo0"
>> smtp_setup_events: listen on 127.0.0.1 port 25 flags 0x0 cert "lo0"
>> smtp: will accept at most 244 clients
>> offline message enqueued
>> session_pickup: greeting client
>> command: helo   args: darwin.crosse.org
>> command: mail from      args: <s...@darwin.crosse.org>
>> session_rfc5321_mail_handler: sending notification to mfa
>> smtp: got imsg_mfa_mail/rcpt
>> smtp: imsg_queue_create_message returned
>> command: rcpt to        args: <s...@crosse.org>
>> smtp: got imsg_mfa_mail/rcpt
>> 1272604479.ozbOZIoTFKlNu1MN: from=<s...@darwin.crosse.org>,
>> relay=darwin.crosse.org [IPv6:2001:470:8:1ee:5ab0:35ff:fe78:c7a0],
>> stat=LocalError (530 5.0.0 Recipient rejected: s...@crosse.org)
>> command: quit   args: (null)
>> session_destroy: killing client: 0x86ce1000
>>
>>
>> From my admittedly very limited knowledge of using gdb, I think the
>> problem is in ruleset.c, in a function called
>> "ruleset_inet6_match()"--however, I've stared at the code now for an
>> hour or two and still have no idea what I'm looking at.  So, here's
>> the big question:  did I overlook something completely obvious and
>> have now gone off the deep end in searching for a bug that's not
>> there?  Any hints or suggestions are welcome.  I think I can say with
>> some level of confidence that this code-path will not work as-is since
>> OpenBSD's inet_net_pton() only accepts AF_INET as the address family
>> argument.  Adding the extra functions from NetBSD's code helped, but I
>> don't know enough about this stuff to know whether the four-odd
>> functions I added are "enough" or if they are really part of a much
>> larger undertaking.
>>
>> Thanks for your time,
>>
>> Seth
>>
>> (conf, dmesg, and changes to libc follow)
>>
>> Note:  this was all done with -current at some point or other.  The
>> dmesg below is from a VMware guest and shows a kernel from the 4/24
>> snapshot, but I've been playing with this stuff on a couple of
>> different machines (all either i386 or amd64).  The other one (real,
>> not virtual, and currently off) was fully up-to-date with -current
>> (kernel and userland) at the time of testing.  The machine below has a
>> kernel and libc (with my tweaks) from 4/24, and smtpd from about an
>> hour ago.
>>
>>
>> s...@bsd ~ $ cat /etc/mail/smtpd.conf
>> #       $OpenBSD: smtpd.conf,v 1.2 2009/11/03 22:32:10 gilles Exp $
>>
>> # This is the smtpd server system-wide configuration file.
>> # See smtpd.conf(5) for more information.
>>
>> listen on lo0
>> listen on vic0
>>
>> map "aliases" { source db "/etc/mail/aliases.db" }
>>
>> accept for local alias aliases deliver to mbox
>> accept for all relay
>>
>> accept from 2001:470:8:1ee::0/64 for all relay
>>
>> ------
>>
>> OpenBSD 4.7-current (GENERIC.MP) #553: Sat Apr 24 14:06:26 MDT 2010
>>     dera...@i386.openbsd.org:/usr/src/sys/arch/i386/compile/GENERIC.MP
>> cpu0: Intel(R) Core(TM)2 Duo CPU E4700 @ 2.60GHz ("GenuineIntel"
>> 686-class) 2.60 GHz
>> cpu0:
FPU,V86,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUS
H,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,SSE3,SSSE3
>> real mem  = 133722112 (127MB)
>> avail mem = 120479744 (114MB)
>> mainbus0 at root
>> bios0 at mainbus0: AT/286+ BIOS, date 09/22/09, BIOS32 rev. 0 @
>> 0xfd780, SMBIOS rev. 2.4 @ 0xe0010 (98 entries)
>> bios0: vendor Phoenix Technologies LTD version "6.00" date 09/22/2009
>> bios0: VMware, Inc. VMware Virtual Platform
>> acpi0 at bios0: rev 2
>> acpi0: tables DSDT FACP BOOT APIC MCFG SRAT
>> acpi0: wakeup devices PCI0(S3) USB_(S1) P2P0(S3) S1F0(S3) S2F0(S3)
>> S3F0(S3) S4F0(S3) S5F0(S3) S6F0(S3) S7F0(S3) S8F0(S3) S9F0(S3)
>> Z00P(S3) Z00Q(S3) Z00R(S3) Z00S(S3) Z00T(S3) Z00U(S3) Z00V(S3)
>> Z00W(S3) Z00X(S3) Z00Y(S3) Z00Z(S3) Z010(S3) Z011(S3) Z012(S3)
>> Z013(S3) Z014(S3) Z015(S3) Z016(S3) Z017(S3) Z018(S3) Z019(S3)
>> Z01A(S3) Z01B(S3) P2P1(S3) S1F0(S3) S2F0(S3) S3F0(S3) S4F0(S3)
>> S5F0(S3) S6F0(S3) S7F0(S3) S8F0(S3) S9F0(S3) Z00P(S3) Z00Q(S3)
>> Z00R(S3) Z00S(S3) Z00T(S3) Z00U(S3) Z00V(S3) Z00W(S3) Z00X(S3)
>> Z00Y(S3) Z00Z(S3) Z010(S3) Z011(S3) Z012(S3) Z013(S3) Z014(S3)
>> Z015(S3) Z016(S3) Z017(S3) Z018(S3) Z019(S3) Z01A(S3) Z01B(S3)
>> P2P2(S3) S1F0(S3) S2F0(S3) S3F0(S3) S4F0(S3) S5F0(S3) S6F0(S3)
>> S7F0(S3) S8F0(S3) S9F0(S3) Z00P(S3) Z00Q(S3) Z00R(S3) Z00S(S3)
>> Z00T(S3) Z00U(S3) Z00V(S3) Z00W(S3) Z00X(S3) Z00Y(S3) Z00Z(S3)
>> Z010(S3) Z011(S3) Z012(S3) Z013(S3) Z014(S3) Z015(S3) Z016(S3)
>> Z017(S3) Z018(S3) Z019(S3) Z01A(S3) Z01B(S3) P2P3(S3) S1F0(S3)
>> S2F0(S3) S3F0(S3) S4F0(S3) S5F0(S3) S6F0(S3) S7F0(S3) S8F0(S3)
>> S9F0(S3) Z00P(S3) Z00Q(S3) Z00R(S3) Z00S(S3) Z00T(S3) Z00U(S3)
>> Z00V(S3) Z00W(S3) Z00X(S3) Z00Y(S3) Z00Z(S3) Z010(S3) Z011(S3)
>> Z012(S3) Z013(S3) Z014(S3) Z015(S3) Z016(S3) Z017(S3) Z018(S3)
>> Z019(S3) Z01A(S3) Z01B(S3) PE40(S3) S1F0(S3) PE50(S3) S1F0(S3)
>> PE60(S3) S1F0(S3) PE70(S3) S1F0(S3) PE80(S3) S1F0(S3) PE90(S3)
>> S1F0(S3) PEA0(S3) S1F0(S3) PEB0(S3) S1F0(S3) PEC0(S3) S1F0(S3)
>> PED0(S3) S1F0(S3) PEE0(S3) S1F0(S3) PE41(S3) S1F0(S3) PE42(S3)
>> S1F0(S3) PE43(S3) S1F0(S3) PE44(S3) S1F0(S3) PE45(S3) S1F0(S3)
>> PE46(S3) S1F0(S3) PE47(S3) S1F0(S3) PE51(S3) S1F0(S3) PE52(S3)
>> S1F0(S3) PE53(S3) S1F0(S3) PE54(S3) S1F0(S3) PE55(S3) S1F0(S3)
>> PE56(S3) S1F0(S3) PE57(S3) S1F0(S3) PE61(S3) S1F0(S3) PE62(S3)
>> S1F0(S3) PE63(S3) S1F0(S3) PE64(S3) S1F0(S3) PE65(S3) S1F0(S3)
>> PE66(S3) S1F0(S3) PE67(S3) S1F0(S3) PE71(S3) S1F0(S3) PE72(S3)
>> S1F0(S3) PE73(S3) S1F0(S3) PE74(S3) S1F0(S3) PE75(S3) S1F0(S3)
>> PE76(S3) S1F0(S3) PE77(S3) S1F0(S3) PE81(S3) S1F0(S3) PE82(S3)
>> S1F0(S3) PE83(S3) S1F0(S3) PE84(S3) S1F0(S3) PE85(S3) S1F0(S3)
>> PE86(S3) S1F0(S3) PE87(S3) S1F0(S3) PE91(S3) S1F0(S3) PE92(S3)
>> S1F0(S3) PE93(S3) S1F0(S3) PE94(S3) S1F0(S3) PE95(S3) S1F0(S3)
>> PE96(S3) S1F0(S3) PE97(S3) S1F0(S3) PEA1(S3) S1F0(S3) PEA2(S3)
>> S1F0(S3) PEA3(S3) S1F0(S3) PEA4(S3) S1F0(S3) PEA5(S3) S1F0(S3)
>> PEA6(S3) S1F0(S3) PEA7(S3) S1F0(S3) PEB1(S3) S1F0(S3) PEB2(S3)
>> S1F0(S3) PEB3(S3) S1F0(S3) PEB4(S3) S1F0(S3) PEB5(S3) S1F0(S3)
>> PEB6(S3) S1F0(S3) PEB7(S3) S1F0(S3) SLPB(S4)
>> acpitimer0 at acpi0: 3579545 Hz, 24 bits
>> acpimadt0 at acpi0 addr 0xfee00000: PC-AT compat
>> cpu0 at mainbus0: apid 0 (boot processor)
>> cpu0: apic clock running at 65MHz
>> cpu1 at mainbus0: apid 1 (application processor)
>> cpu1: Intel(R) Core(TM)2 Duo CPU E4700 @ 2.60GHz ("GenuineIntel"
>> 686-class) 2.60 GHz
>> cpu1:
FPU,V86,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUS
H,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,SSE3,SSSE3
>> ioapic0 at mainbus0: apid 2 pa 0xfec00000, version 11, 24 pins
>> acpiprt0 at acpi0: bus 0 (PCI0)
>> acpicpu0 at acpi0
>> acpicpu1 at acpi0
>> acpibat0 at acpi0: BAT1 not present
>> acpibat1 at acpi0: BAT2 not present
>> acpiac0 at acpi0: AC unit online
>> acpibtn0 at acpi0: SLPB
>> bios0: ROM list: 0xc0000/0x8000 0xc8000/0x1e00! 0xca000/0x1000
>> 0xdc000/0x4000! 0xe0000/0x4000!
>> pci0 at mainbus0 bus 0: configuration mode 1 (bios)
>> pchb0 at pci0 dev 0 function 0 "Intel 82443BX AGP" rev 0x01
>> ppb0 at pci0 dev 1 function 0 "Intel 82443BX AGP" rev 0x01
>> pci1 at ppb0 bus 1
>> piixpcib0 at pci0 dev 7 function 0 "Intel 82371AB PIIX4 ISA" rev 0x08
>> pciide0 at pci0 dev 7 function 1 "Intel 82371AB IDE" rev 0x01: DMA,
>> channel 0 configured to compatibility, channel 1 configured to
>> compatibility
>> pciide0: channel 0 ignored (disabled)
>> atapiscsi0 at pciide0 channel 1 drive 0
>> scsibus0 at atapiscsi0: 2 targets
>> cd0 at scsibus0 targ 0 lun 0: <NECVMWar, VMware IDE CDR10, 1.00> ATAPI
>> 5/cdrom removable
>> cd0(pciide0:1:0): using PIO mode 4, Ultra-DMA mode 2
>> piixpm0 at pci0 dev 7 function 3 "Intel 82371AB Power" rev 0x08: SMBus
disabled
>> "VMware Virtual Machine Communication Interface" rev 0x10 at pci0 dev
>> 7 function 7 not configured
>> vga1 at pci0 dev 15 function 0 "VMware Virtual SVGA II" rev 0x00
>> wsdisplay0 at vga1 mux 1: console (80x25, vt100 emulation)
>> wsdisplay0: screen 1-5 added (80x25, vt100 emulation)
>> mpi0 at pci0 dev 16 function 0 "Symbios Logic 53c1030" rev 0x01: apic
>> 2 int 17 (irq 11)
>> scsibus1 at mpi0: 16 targets, initiator 7
>> sd0 at scsibus1 targ 0 lun 0: <VMware, Virtual disk, 1.0> SCSI2 0/direct
fixed
>> sd0: 51200MB, 512 bytes/sec, 104857600 sec total
>> sd1 at scsibus1 targ 1 lun 0: <VMware, Virtual disk, 1.0> SCSI2 0/direct
fixed
>> sd1: 102400MB, 512 bytes/sec, 209715200 sec total
>> sd2 at scsibus1 targ 2 lun 0: <VMware, Virtual disk, 1.0> SCSI2 0/direct
fixed
>> sd2: 102400MB, 512 bytes/sec, 209715200 sec total
>> mpi0: target 0 Sync at 160MHz width 16bit offset 127 QAS 1 DT 1 IU 1
>> mpi0: target 1 Sync at 160MHz width 16bit offset 127 QAS 1 DT 1 IU 1
>> mpi0: target 2 Sync at 160MHz width 16bit offset 127 QAS 1 DT 1 IU 1
>> ppb1 at pci0 dev 17 function 0 "VMware Virtual PCI-PCI" rev 0x02
>> pci2 at ppb1 bus 2
>> vic0 at pci2 dev 0 function 0 "AMD 79c970 PCnet-PCI" rev 0x10: apic 2
>> int 18 (irq 10), address 00:0c:29:18:19:84
>> ppb2 at pci0 dev 21 function 0 "VMware Virtual PCIE-PCIE" rev 0x01
>> pci3 at ppb2 bus 3
>> ppb3 at pci0 dev 21 function 1 "VMware Virtual PCIE-PCIE" rev 0x01
>> pci4 at ppb3 bus 4
>> ppb4 at pci0 dev 21 function 2 "VMware Virtual PCIE-PCIE" rev 0x01
>> pci5 at ppb4 bus 5
>> ppb5 at pci0 dev 21 function 3 "VMware Virtual PCIE-PCIE" rev 0x01
>> pci6 at ppb5 bus 6
>> ppb6 at pci0 dev 21 function 4 "VMware Virtual PCIE-PCIE" rev 0x01
>> pci7 at ppb6 bus 7
>> ppb7 at pci0 dev 21 function 5 "VMware Virtual PCIE-PCIE" rev 0x01
>> pci8 at ppb7 bus 8
>> ppb8 at pci0 dev 21 function 6 "VMware Virtual PCIE-PCIE" rev 0x01
>> pci9 at ppb8 bus 9
>> ppb9 at pci0 dev 21 function 7 "VMware Virtual PCIE-PCIE" rev 0x01
>> pci10 at ppb9 bus 10
>> ppb10 at pci0 dev 22 function 0 "VMware Virtual PCIE-PCIE" rev 0x01
>> pci11 at ppb10 bus 11
>> ppb11 at pci0 dev 22 function 1 "VMware Virtual PCIE-PCIE" rev 0x01
>> pci12 at ppb11 bus 12
>> ppb12 at pci0 dev 22 function 2 "VMware Virtual PCIE-PCIE" rev 0x01
>> pci13 at ppb12 bus 13
>> ppb13 at pci0 dev 22 function 3 "VMware Virtual PCIE-PCIE" rev 0x01
>> pci14 at ppb13 bus 14
>> ppb14 at pci0 dev 22 function 4 "VMware Virtual PCIE-PCIE" rev 0x01
>> pci15 at ppb14 bus 15
>> ppb15 at pci0 dev 22 function 5 "VMware Virtual PCIE-PCIE" rev 0x01
>> pci16 at ppb15 bus 16
>> ppb16 at pci0 dev 22 function 6 "VMware Virtual PCIE-PCIE" rev 0x01
>> pci17 at ppb16 bus 17
>> ppb17 at pci0 dev 22 function 7 "VMware Virtual PCIE-PCIE" rev 0x01
>> pci18 at ppb17 bus 18
>> ppb18 at pci0 dev 23 function 0 "VMware Virtual PCIE-PCIE" rev 0x01
>> pci19 at ppb18 bus 19
>> ppb19 at pci0 dev 23 function 1 "VMware Virtual PCIE-PCIE" rev 0x01
>> pci20 at ppb19 bus 20
>> ppb20 at pci0 dev 23 function 2 "VMware Virtual PCIE-PCIE" rev 0x01
>> pci21 at ppb20 bus 21
>> ppb21 at pci0 dev 23 function 3 "VMware Virtual PCIE-PCIE" rev 0x01
>> pci22 at ppb21 bus 22
>> ppb22 at pci0 dev 23 function 4 "VMware Virtual PCIE-PCIE" rev 0x01
>> pci23 at ppb22 bus 23
>> ppb23 at pci0 dev 23 function 5 "VMware Virtual PCIE-PCIE" rev 0x01
>> pci24 at ppb23 bus 24
>> ppb24 at pci0 dev 23 function 6 "VMware Virtual PCIE-PCIE" rev 0x01
>> pci25 at ppb24 bus 25
>> ppb25 at pci0 dev 23 function 7 "VMware Virtual PCIE-PCIE" rev 0x01
>> pci26 at ppb25 bus 26
>> ppb26 at pci0 dev 24 function 0 "VMware Virtual PCIE-PCIE" rev 0x01
>> pci27 at ppb26 bus 27
>> ppb27 at pci0 dev 24 function 1 "VMware Virtual PCIE-PCIE" rev 0x01
>> pci28 at ppb27 bus 28
>> ppb28 at pci0 dev 24 function 2 "VMware Virtual PCIE-PCIE" rev 0x01
>> pci29 at ppb28 bus 29
>> ppb29 at pci0 dev 24 function 3 "VMware Virtual PCIE-PCIE" rev 0x01
>> pci30 at ppb29 bus 30
>> ppb30 at pci0 dev 24 function 4 "VMware Virtual PCIE-PCIE" rev 0x01
>> pci31 at ppb30 bus 31
>> ppb31 at pci0 dev 24 function 5 "VMware Virtual PCIE-PCIE" rev 0x01
>> pci32 at ppb31 bus 32
>> ppb32 at pci0 dev 24 function 6 "VMware Virtual PCIE-PCIE" rev 0x01
>> pci33 at ppb32 bus 33
>> ppb33 at pci0 dev 24 function 7 "VMware Virtual PCIE-PCIE" rev 0x01
>> pci34 at ppb33 bus 34
>> isa0 at piixpcib0
>> isadma0 at isa0
>> com0 at isa0 port 0x3f8/8 irq 4: ns16550a, 16 byte fifo
>> com1 at isa0 port 0x2f8/8 irq 3: ns16550a, 16 byte fifo
>> pckbc0 at isa0 port 0x60/5
>> pckbd0 at pckbc0 (kbd slot)
>> pckbc0: using irq 1 for kbd slot
>> wskbd0 at pckbd0: console keyboard, using wsdisplay0
>> pmsi0 at pckbc0 (aux slot)
>> pckbc0: using irq 12 for aux slot
>> wsmouse0 at pmsi0 mux 0
>> pcppi0 at isa0 port 0x61
>> midi0 at pcppi0: <PC speaker>
>> spkr0 at pcppi0
>> lpt0 at isa0 port 0x378/4 irq 7
>> npx0 at isa0 port 0xf0/16: reported by CPUID; using exception 16
>> fdc0 at isa0 port 0x3f0/6 irq 6 drq 2
>> fd0 at fdc0 drive 0: 1.44MB 80 cyl, 2 head, 18 sec
>> mtrr: Pentium Pro MTRR support
>> vscsi0 at root
>> scsibus2 at vscsi0: 256 targets
>> softraid0 at root
>> root on sd0a swap on sd0b dump on sd0b
>>
>> ------------------
>>
>> Finally, here's the diff of what I pulled from NetBSD and applied to libc:
>>
>>
>> Index: inet_net_ntop.c
>> ===================================================================
>> RCS file: /cvs/src/lib/libc/net/inet_net_ntop.c,v
>> retrieving revision 1.6
>> diff -u -p inet_net_ntop.c
>> --- inet_net_ntop.c   6 Aug 2005 20:30:03 -0000       1.6
>> +++ inet_net_ntop.c   30 Apr 2010 05:52:37 -0000
>> @@ -27,7 +27,8 @@
>>  #include <string.h>
>>  #include <stdlib.h>
>>
>> -static char *inet_net_ntop_ipv4(const u_char *, int, char *, size_t);
>> +static char *        inet_net_ntop_ipv4(const u_char *, int, char *,
size_t);
>> +static char *        inet_net_ntop_ipv6(const u_char *, int, char *,
size_t);
>>
>>  /*
>>   * char *
>> @@ -45,6 +46,8 @@ inet_net_ntop(int af, const void *src, int bits, char
>>       switch (af) {
>>       case AF_INET:
>>               return (inet_net_ntop_ipv4(src, bits, dst, size));
>> +     case AF_INET6:
>> +             return (inet_net_ntop_ipv6(src, bits, dst, size));
>>       default:
>>               errno = EAFNOSUPPORT;
>>               return (NULL);
>> @@ -130,6 +133,152 @@ inet_net_ntop_ipv4(const u_char *src, int bits, char
*
>>       return (odst);
>>
>>   emsgsize:
>> +     errno = EMSGSIZE;
>> +     return (NULL);
>> +}
>> +
>> +/*
>> + * static char *
>> + * inet_net_ntop_ipv6(src, bits, fakebits, dst, size)
>> + *   convert IPv6 network number from network to presentation format.
>> + *   generates CIDR style result always. Picks the shortest
representation
>> + *   unless the IP is really IPv4.
>> + *   always prints specified number of bits (bits).
>> + * return:
>> + *   pointer to dst, or NULL if an error occurred (check errno).
>> + * note:
>> + *   network byte order assumed.  this means 192.5.5.240/28 has
>> + *   0x11110000 in its fourth octet.
>> + * author:
>> + *   Vadim Kogan (UCB), June 2001
>> + *  Original version (IPv4) by Paul Vixie (ISC), July 1996
>> + */
>> +
>> +static char *
>> +inet_net_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size)
>> +{
>> +     size_t  bytes;
>> +     u_int   m;
>> +     int     b;
>> +     int     p;
>> +     int     zero_s, zero_l, tmp_zero_s, tmp_zero_l;
>> +     int     i;
>> +     int     is_ipv4 = 0;
>> +     u_char inbuf[16];
>> +     char
outbuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
>> +     char    *cp;
>> +     int     words;
>> +     u_char  *s;
>> +     char    *ep;
>> +     int     advance;
>> +
>> +     if (bits < 0 || bits > 128) {
>> +             errno = EINVAL;
>> +             return (NULL);
>> +     }
>> +
>> +     cp = outbuf;
>> +     ep = outbuf + sizeof(outbuf);
>> +
>> +     if (bits == 0) {
>> +             *cp++ = ':';
>> +             *cp++ = ':';
>> +             *cp = '\0';
>> +     } else {
>> +             /* Copy src to private buffer.  Zero host part. */
>> +             bytes = (bits + 7) / 8;
>> +             memcpy(inbuf, src, bytes);
>> +             memset(inbuf + bytes, 0, 16 - bytes);
>> +             b = bits % 8;
>> +             if (b != 0) {
>> +                     m = ~0 << (8 - b);
>> +                     inbuf[bytes-1] &= m;
>> +             }
>> +
>> +             s = inbuf;
>> +
>> +             /* how many words need to be displayed in output */
>> +             words = (bits + 15) / 16;
>> +             if (words == 1)
>> +                     words = 2;
>> +
>> +             /* Find the longest substring of zero's */
>> +             zero_s = zero_l = tmp_zero_s = tmp_zero_l = 0;
>> +             for (i = 0; i < (words * 2); i += 2) {
>> +                     if ((s[i] | s[i+1]) == 0) {
>> +                             if (tmp_zero_l == 0)
>> +                                     tmp_zero_s = i / 2;
>> +                             tmp_zero_l++;
>> +                     } else {
>> +                             if (tmp_zero_l && zero_l < tmp_zero_l) {
>> +                                     zero_s = tmp_zero_s;
>> +                                     zero_l = tmp_zero_l;
>> +                                     tmp_zero_l = 0;
>> +                             }
>> +                     }
>> +             }
>> +
>> +             if (tmp_zero_l && zero_l < tmp_zero_l) {
>> +                     zero_s = tmp_zero_s;
>> +                     zero_l = tmp_zero_l;
>> +             }
>> +
>> +             if (zero_l != words && zero_s == 0 && ((zero_l == 6) ||
>> +                 ((zero_l == 5 && s[10] == 0xff && s[11] == 0xff) ||
>> +                 ((zero_l == 7 && s[14] != 0 && s[15] != 1)))))
>> +                     is_ipv4 = 1;
>> +
>> +             /* Format whole words. */
>> +             for (p = 0; p < words; p++) {
>> +                     if (zero_l != 0 && p >= zero_s && p < zero_s +
zero_l) {
>> +                             /* Time to skip some zeros */
>> +                             if (p == zero_s)
>> +                                     *cp++ = ':';
>> +                             if (p == words - 1)
>> +                                     *cp++ = ':';
>> +                             s++;
>> +                             s++;
>> +                             continue;
>> +                     }
>> +
>> +                     if (is_ipv4 && p > 5) {
>> +                             *cp++ = (p == 6) ? ':' : '.';
>> +                             advance = snprintf(cp, (size_t)(ep - cp),
>> +                                 "%u", *s++);
>> +                             if (advance <= 0 || advance >= ep - cp)
>> +                                     goto emsgsize;
>> +                             cp += advance;
>> +                             /* we can potentially drop the last octet */
>> +                             if (p != 7 || bits > 120) {
>> +                                     *cp++ = '.';
>> +                                     advance = snprintf(cp,
>> +                                         (size_t)(ep - cp), "%u", *s++);
>> +                                     if (advance <= 0 || advance >= ep -
cp)
>> +                                             goto emsgsize;
>> +                                     cp += advance;
>> +                             }
>> +                     } else {
>> +                             if (cp != outbuf)
>> +                                     *cp++ = ':';
>> +                             advance = snprintf(cp, (size_t)(ep - cp),
"%x",
>> +                                 *s * 256 + s[1]);
>> +                             if (advance <= 0 || advance >= ep - cp)
>> +                                     goto emsgsize;
>> +                             cp += advance;
>> +                             s += 2;
>> +                     }
>> +             }
>> +     }
>> +     /* Format CIDR /width. */
>> +     /* LINTED */
>> +     snprintf(cp, ep - cp, "/%u", bits);
>> +     if (strlen(outbuf) + 1 > size)
>> +             goto emsgsize;
>> +     strlcpy(dst, outbuf, size);
>> +
>> +     return (dst);
>> +
>> +emsgsize:
>>       errno = EMSGSIZE;
>>       return (NULL);
>>  }
>> Index: inet_net_pton.c
>> ===================================================================
>> RCS file: /cvs/src/lib/libc/net/inet_net_pton.c,v
>> retrieving revision 1.6
>> diff -u -p inet_net_pton.c
>> --- inet_net_pton.c   1 Sep 2008 09:40:43 -0000       1.6
>> +++ inet_net_pton.c   30 Apr 2010 05:52:37 -0000
>> @@ -21,6 +21,7 @@
>>  #include <sys/socket.h>
>>  #include <netinet/in.h>
>>  #include <arpa/inet.h>
>> +#include <arpa/nameser.h>
>>
>>  #include <assert.h>
>>  #include <ctype.h>
>> @@ -30,6 +31,9 @@
>>  #include <stdlib.h>
>>
>>  static int   inet_net_pton_ipv4(const char *, u_char *, size_t);
>> +static int   inet_net_pton_ipv6(const char *, u_char *, size_t);
>> +static int   getbits(const char *, int *);
>> +static int   getv4(const char *, u_char *, int *);
>>
>>  /*
>>   * static int
>> @@ -50,6 +54,8 @@ inet_net_pton(int af, const char *src, void *dst, size
>>       switch (af) {
>>       case AF_INET:
>>               return (inet_net_pton_ipv4(src, dst, size));
>> +     case AF_INET6:
>> +             return (inet_net_pton_ipv6(src, dst, size));
>>       default:
>>               errno = EAFNOSUPPORT;
>>               return (-1);
>> @@ -179,6 +185,201 @@ inet_net_pton_ipv4(const char *src, u_char *dst,
size_
>>                       goto emsgsize;
>>               *dst++ = '\0';
>>       }
>> +     return (bits);
>> +
>> + enoent:
>> +     errno = ENOENT;
>> +     return (-1);
>> +
>> + emsgsize:
>> +     errno = EMSGSIZE;
>> +     return (-1);
>> +}
>> +
>> +static int
>> +getbits(const char *src, int *bitsp)
>> +{
>> +     static const char digits[] = "0123456789";
>> +     int n;
>> +     int val;
>> +     char ch;
>> +
>> +     val = 0;
>> +     n = 0;
>> +     while ((ch = *src++) != '\0') {
>> +             const char *pch;
>> +
>> +             pch = strchr(digits, ch);
>> +             if (pch != NULL) {
>> +                     if (n++ != 0 && val == 0)       /* no leading zeros
*/
>> +                             return (0);
>> +                     val *= 10;
>> +                     val += (pch - digits);
>> +                     if (val > 128)                  /* range */
>> +                             return (0);
>> +                     continue;
>> +             }
>> +             return (0);
>> +     }
>> +     if (n == 0)
>> +             return (0);
>> +     *bitsp = val;
>> +     return (1);
>> +}
>> +
>> +static int
>> +getv4(const char *src, u_char *dst, int *bitsp)
>> +{
>> +     static const char digits[] = "0123456789";
>> +     u_char *odst = dst;
>> +     int n;
>> +     u_int val;
>> +     char ch;
>> +
>> +     val = 0;
>> +     n = 0;
>> +     while ((ch = *src++) != '\0') {
>> +             const char *pch;
>> +
>> +             pch = strchr(digits, ch);
>> +             if (pch != NULL) {
>> +                     if (n++ != 0 && val == 0)       /* no leading zeros
*/
>> +                             return (0);
>> +                     val *= 10;
>> +                     val += (pch - digits);
>> +                     if (val > 255)                  /* range */
>> +                             return (0);
>> +                     continue;
>> +             }
>> +             if (ch == '.' || ch == '/') {
>> +                     if (dst - odst > 3)             /* too many octets?
*/
>> +                             return (0);
>> +                     *dst++ = val;
>> +                     if (ch == '/')
>> +                             return (getbits(src, bitsp));
>> +                     val = 0;
>> +                     n = 0;
>> +                     continue;
>> +             }
>> +             return (0);
>> +     }
>> +     if (n == 0)
>> +             return (0);
>> +     if (dst - odst > 3)             /* too many octets? */
>> +             return (0);
>> +     *dst++ = val;
>> +     return (1);
>> +}
>> +
>> +static int
>> +inet_net_pton_ipv6(const char *src, u_char *dst, size_t size)
>> +{
>> +     static const char xdigits_l[] = "0123456789abcdef",
>> +                       xdigits_u[] = "0123456789ABCDEF";
>> +     u_char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
>> +     const char *xdigits, *curtok;
>> +     int ch, saw_xdigit;
>> +     u_int val;
>> +     int digits;
>> +     int bits;
>> +     size_t bytes;
>> +     int words;
>> +     int ipv4;
>> +
>> +     memset((tp = tmp), '\0', IN6ADDRSZ);
>> +     endp = tp + IN6ADDRSZ;
>> +     colonp = NULL;
>> +     /* Leading :: requires some special handling. */
>> +     if (*src == ':')
>> +             if (*++src != ':')
>> +                     goto enoent;
>> +     curtok = src;
>> +     saw_xdigit = 0;
>> +     val = 0;
>> +     digits = 0;
>> +     bits = -1;
>> +     ipv4 = 0;
>> +     while ((ch = *src++) != '\0') {
>> +             const char *pch;
>> +
>> +             if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
>> +                     pch = strchr((xdigits = xdigits_u), ch);
>> +             if (pch != NULL) {
>> +                     val <<= 4;
>> +                     val |= (pch - xdigits);
>> +                     if (++digits > 4)
>> +                             goto enoent;
>> +                     saw_xdigit = 1;
>> +                     continue;
>> +             }
>> +             if (ch == ':') {
>> +                     curtok = src;
>> +                     if (!saw_xdigit) {
>> +                             if (colonp)
>> +                                     goto enoent;
>> +                             colonp = tp;
>> +                             continue;
>> +                     } else if (*src == '\0')
>> +                             goto enoent;
>> +                     if (tp + INT16SZ > endp)
>> +                             return (0);
>> +                     *tp++ = (u_char) (val >> 8) & 0xff;
>> +                     *tp++ = (u_char) val & 0xff;
>> +                     saw_xdigit = 0;
>> +                     digits = 0;
>> +                     val = 0;
>> +                     continue;
>> +             }
>> +             if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
>> +                  getv4(curtok, tp, &bits) > 0) {
>> +                     tp += INADDRSZ;
>> +                     saw_xdigit = 0;
>> +                     ipv4 = 1;
>> +                     break;  /* '\0' was seen by inet_pton4(). */
>> +             }
>> +             if (ch == '/' && getbits(src, &bits) > 0)
>> +                     break;
>> +             goto enoent;
>> +     }
>> +     if (saw_xdigit) {
>> +             if (tp + INT16SZ > endp)
>> +                     goto enoent;
>> +             *tp++ = (u_char) (val >> 8) & 0xff;
>> +             *tp++ = (u_char) val & 0xff;
>> +     }
>> +     if (bits == -1)
>> +             bits = 128;
>> +
>> +     words = (bits + 15) / 16;
>> +     if (words < 2)
>> +             words = 2;
>> +     if (ipv4)
>> +             words = 8;
>> +     endp =  tmp + 2 * words;
>> +
>> +     if (colonp != NULL) {
>> +             /*
>> +              * Since some memmove()'s erroneously fail to handle
>> +              * overlapping regions, we'll do the shift by hand.
>> +              */
>> +             const int n = tp - colonp;
>> +             int i;
>> +
>> +             if (tp == endp)
>> +                     goto enoent;
>> +             for (i = 1; i <= n; i++) {
>> +                     endp[- i] = colonp[n - i];
>> +                     colonp[n - i] = 0;
>> +             }
>> +             tp = endp;
>> +     }
>> +     if (tp != endp)
>> +             goto enoent;
>> +
>> +     bytes = (bits + 7) / 8;
>> +     if (bytes > size)
>> +             goto emsgsize;
>> +     memcpy(dst, tmp, bytes);
>>       return (bits);
>>
>>   enoent:
>>
>
> --
> Gilles Chehade
> freelance developer/sysadmin/consultant
>
>                   http://www.poolp.org

Reply via email to