Created
July 1, 2013 15:18
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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