Skip to content

Instantly share code, notes, and snippets.

@drocamor
Created July 1, 2013 15:18
Show Gist options
  • Save drocamor/5901751 to your computer and use it in GitHub Desktop.
Save drocamor/5901751 to your computer and use it in GitHub Desktop.
I want to use core.logic to help me find out if an IP is inside of a network. core.logic doesn't have bitwise operations in it now, so I tried to rig one up my self. The code is tedious and runs pretty slowly, but it is sort of neat to see it start to work.
(ns networks.core
(:refer-clojure :exclude [==])
(:use [clojure.core.logic])
(:require [clojure.core.logic.fd :as fd]))
(defn bit-ando
"Ensure that r is a bitwise AND of x and y."
[x y r]
(conde
[(== 0 x) (== 0 y) (== 0 r)]
[(== 1 x) (== 0 y) (== 0 r)]
[(== 0 x) (== 1 y) (== 0 r)]
[(== 1 x) (== 1 y) (== 1 r)]))
(defn bit-numero
"Ensure that n is an integer between 0 and 255 and
bits is a vector of bits that represent n."
[n bits]
(fresh [b0 b1 b2 b3 b4 b5 b6 b7]
(fd/in n (fd/interval 0 255))
(fd/in b0 b1 b2 b3 b4 b5 b6 b7 (fd/interval 0 1))
(fd/eq
(= n
(+
(* b0 1)
(* b1 2)
(* b2 4)
(* b3 8)
(* b4 16)
(* b5 32)
(* b6 64)
(* b7 128))))
(== bits [b7 b6 b5 b4 b3 b2 b1 b0])))
(defn num-bit-ando
"Ensure that r is the integer representation of a
bitwise AND between n and m."
[n m r]
(fresh [n0 n1 n2 n3 n4 n5 n6 n7
m0 m1 m2 m3 m4 m5 m6 m7
r0 r1 r2 r3 r4 r5 r6 r7]
(bit-numero n [n7 n6 n5 n4 n3 n2 n1 n0])
(bit-numero m [m7 m6 m5 m4 m3 m2 m1 m0])
(bit-ando m0 n0 r0)
(bit-ando m1 n1 r1)
(bit-ando m2 n2 r2)
(bit-ando m3 n3 r3)
(bit-ando m4 n4 r4)
(bit-ando m5 n5 r5)
(bit-ando m6 n6 r6)
(bit-ando m7 n7 r7)
(bit-numero r [r7 r6 r5 r4 r3 r2 r1 r0])))
(defn octeto
"Ensure that a bitwise AND m unify with n bitwise AND m."
[a n m]
(fresh [a-masked n-masked]
(fd/in a n m a-masked n-masked (fd/interval 0 255))
(num-bit-ando a m a-masked)
(num-bit-ando n m n-masked)
(== a-masked n-masked)))
(defn networko
"Ensure that an address is in a network with a mask."
[address network mask]
(fresh [a1 a2 a3 a4
n1 n2 n3 n4
m1 m2 m3 m4]
(fd/in a1 a2 a3 a4
n1 n2 n3 n4
m1 m2 m3 m4
(fd/interval 0 255))
(== address [a1 a2 a3 a4])
(== network [n1 n2 n3 n4])
(== mask [m1 m2 m3 m4])
(fd/>= m1 m2)
(fd/>= m2 m3)
(fd/>= m3 m4)
(octeto a1 n1 m1)
(octeto a2 n2 m2)
(octeto a3 n3 m3)
(octeto a4 n4 m4)))
;; Find 5 IPs in the 192.168.0/24 network
(run 5 [q]
(networko q
[192 168 1 0]
[255 255 255 0]))
;; Find a /24 network that can hold 192.168.200.4
(run 1 [net]
(networko [192 168 200 4]
net
[255 255 255 0]))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment