Mirror: Best-effort discovery of the machine's local network using just Node.js dgram sockets
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix: check subnet for dhcp discovery (#12)

* fix: check subnet for dhcp discovery

* Add changeset

---------

Co-authored-by: Phil Pluckthun <phil@kitten.sh>

authored by

Stephen Zhou
Phil Pluckthun
and committed by
GitHub
f5b38f9c 463aba4c

+37 -1
+5
.changeset/shaggy-walls-argue.md
··· 1 + --- 2 + 'lan-network': patch 3 + --- 4 + 5 + Compare subnet-masked addresses before accepting DHCP discover message
+14
src/__tests__/network.test.ts
··· 6 6 toIpStr, 7 7 interfaceAssignments, 8 8 matchAssignment, 9 + isSameSubnet, 9 10 } from '../network'; 10 11 11 12 describe(parseMacStr, () => { ··· 30 31 expect(toIpStr(parseIpStr(addr))).toBe(addr); 31 32 } 32 33 ); 34 + }); 35 + 36 + describe(isSameSubnet, () => { 37 + it('returns true for same subnet', () => { 38 + expect(isSameSubnet('192.168.1.1', '192.168.1.2', '255.255.255.0')).toBe( 39 + true 40 + ); 41 + }); 42 + it('returns false for different subnet', () => { 43 + expect(isSameSubnet('192.168.1.1', '192.168.2.1', '255.255.255.0')).toBe( 44 + false 45 + ); 46 + }); 33 47 }); 34 48 35 49 describe(interfaceAssignments, () => {
+7 -1
src/dhcp.ts
··· 1 1 import { randomBytes } from 'node:crypto'; 2 2 import { createSocket } from 'node:dgram'; 3 - import { parseIpStr, toIpStr, parseMacStr } from './network'; 3 + import { parseIpStr, toIpStr, parseMacStr, isSameSubnet } from './network'; 4 4 import type { NetworkAssignment } from './types'; 5 5 6 6 class DHCPTimeoutError extends TypeError { ··· 57 57 const socket = createSocket( 58 58 { type: 'udp4', reuseAddr: true }, 59 59 (_msg, rinfo) => { 60 + if ( 61 + !isSameSubnet(rinfo.address, assignment.address, assignment.netmask) 62 + ) { 63 + return; 64 + } 65 + 60 66 clearTimeout(timeout); 61 67 resolve(rinfo.address); 62 68 socket.close();
+11
src/network.ts
··· 26 26 return addr[3] | (addr[2] << 8) | (addr[1] << 16) | (addr[0] << 24); 27 27 }; 28 28 29 + export const isSameSubnet = ( 30 + addrA: string, 31 + addrB: string, 32 + netmask: string 33 + ): boolean => { 34 + const rawAddrA = parseIpStr(addrA); 35 + const rawAddrB = parseIpStr(addrB); 36 + const rawMask = parseIpStr(netmask); 37 + return (rawAddrA & rawMask) === (rawAddrB & rawMask); 38 + }; 39 + 29 40 export const toIpStr = (addr: number): string => { 30 41 const MASK = (1 << 8) - 1; 31 42 let ipStr = '';