I'm stuck here with a query that kills postgresql backend.
I've installed postgresql 7.3.1 on two machines..
one with gcc 3.2, glibc 2.3.1 source based (a)
and the other with gcc 2.95.3, glibc 2.2.3 slackware 8 (b)
both are PIII with kernel 2.4.20.
(a) has ext3 and (b) has xfs for the database storage...
tested both with altered and original postgresql.conf...
I've the same program installed on both machines using the same database...
both fail when i'm executing a specific query...
Those are the errors (I've removed a lot from the queries to isolate the
problem):
This fails:
netinfo=> select * from view_all v where NOT EXISTS ( SELECT * FROM history h
WHERE ( h.ip = v.ip OR ( h.ip IS NULL AND v.ip IS NULL ) ) AND v.sw_ip IS
NULL AND ( h.mac = v.mac OR ( h.mac IS NULL AND v.mac IS NULL ) ) );
ERROR: replace_vars_with_subplan_refs: variable not in subplan target list
but this works:
netinfo=> select * from view_all v where NOT EXISTS ( SELECT * FROM history h
WHERE ( h.ip = v.ip OR ( h.ip IS NULL AND v.ip IS NULL ) ) AND ( h.mac =
v.mac OR ( h.mac IS NULL AND v.mac IS NULL ) ) );
this fails too:
netinfo=> select * from view_all v where NOT EXISTS ( SELECT * FROM history h
WHERE ( h.ip = v.ip OR ( h.ip IS NULL AND v.ip IS NULL ) ) AND ( h.mac =
v.mac OR ( h.mac IS NULL AND v.mac IS NULL ) ) AND ( ( h.sw_ip IS NULL AND
v.sw_ip IS NULL ) ) );
ERROR: replace_vars_with_subplan_refs: variable not in subplan target list
and this causes a segmentation fault:
netinfo=> select * from view_all v where NOT EXISTS ( SELECT * FROM history h
WHERE ( h.ip = v.ip OR ( h.ip IS NULL AND v.ip IS NULL ) ) AND ( h.mac =
v.mac OR ( h.mac IS NULL AND v.mac IS NULL ) ) AND ( h.sw_ip = v.sw_ip OR (
h.sw_ip IS NULL AND v.sw_ip IS NULL ) ) );
server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
The connection to the server was lost. Attempting reset: Failed.
To reproduce it:
createdb test
createlang plpgsql test
psql -f create.sql test
and then run this:
select * from view_all v where NOT EXISTS ( SELECT * FROM history h WHERE (
h.ip = v.ip OR ( h.ip IS NULL AND v.ip IS NULL ) ) AND ( h.mac = v.mac OR (
h.mac IS NULL AND v.mac IS NULL ) ) AND ( h.sw_ip = v.sw_ip OR ( h.sw_ip IS
NULL AND v.sw_ip IS NULL ) ) );
<<V13>>
--
Key fingerprint: 7448 3D26 EA5D 275C 749A B597 3576 0073 6AD2 9335
CREATE TABLE netdevs(
ip VARCHAR(256)
PRIMARY KEY,
dev_type INT4
NOT NULL,
name VARCHAR(256)
NOT NULL,
community VARCHAR(256)
NOT NULL,
first_found INT8
DEFAULT '0'
NOT NULL,
last_found INT8
DEFAULT '0'
NOT NULL
) WITHOUT OIDS;
CREATE TABLE interfaces(
netdev_ip VARCHAR(256)
NOT NULL
REFERENCES netdevs(ip)
ON DELETE CASCADE
ON UPDATE CASCADE,
ifindex INT4
NOT NULL,
ifinternal INT4,
description VARCHAR(256),
alias VARCHAR(256),
has_netdev INT4,
PRIMARY KEY(netdev_ip, ifindex)
) WITHOUT OIDS;
CREATE TABLE macs(
mac VARCHAR(256)
NOT NULL,
netdev_ip VARCHAR(256)
NOT NULL,
ifindex INT4
NOT NULL,
PRIMARY KEY (mac,netdev_ip),
FOREIGN KEY (netdev_ip, ifindex)
REFERENCES interfaces(netdev_ip, ifindex)
ON DELETE CASCADE
ON UPDATE CASCADE
) WITHOUT OIDS;
CREATE TABLE ips(
ip VARCHAR(256)
NOT NULL,
mac VARCHAR(256)
NOT NULL,
netdev_ip VARCHAR(256)
NOT NULL,
ifindex INT4
NOT NULL,
PRIMARY KEY(ip,mac,netdev_ip),
FOREIGN KEY(netdev_ip,ifindex)
REFERENCES interfaces(netdev_ip, ifindex)
ON DELETE CASCADE
ON UPDATE CASCADE
) WITHOUT OIDS;
CREATE TABLE vendors(
prefix VARCHAR(50)
PRIMARY KEY
NOT NULL,
name VARCHAR(256)
) WITHOUT OIDS;
CREATE SEQUENCE seq_history;
CREATE TABLE history(
id INT4
PRIMARY KEY
DEFAULT NEXTVAL('seq_history'),
ts INT8
NOT NULL
DEFAULT EXTRACT(EPOCH FROM CURRENT_TIMESTAMP),
last_ts INT8
NOT NULL
DEFAULT EXTRACT(EPOCH FROM CURRENT_TIMESTAMP),
ip VARCHAR(256),
-- NOT NULL,
mac VARCHAR(256),
-- NOT NULL,
router_ip VARCHAR(256),
router_name VARCHAR(256),
router_ifindex INT4,
router_ifdescr VARCHAR(256),
router_ifalias VARCHAR(256),
sw_ip VARCHAR(256),
sw_name VARCHAR(256),
sw_ifindex INT4,
sw_ifdescr VARCHAR(256),
sw_ifalias VARCHAR(256)
-- PRIMARY KEY(ts,ip,mac)
) WITHOUT OIDS;
CREATE TABLE history_state(
hist_id INT4
PRIMARY KEY
REFERENCES history(id)
ON DELETE CASCADE
ON UPDATE CASCADE,
last_ignore INT8,
description TEXT
) WITHOUT OIDS;
CREATE SEQUENCE seq_history_ignore;
CREATE TABLE history_ignore(
id INT4
PRIMARY KEY
DEFAULT NEXTVAL('seq_history_ignore'),
ip VARCHAR(256),
mac VARCHAR(256),
router_name VARCHAR(256),
router_ifindex VARCHAR(256),
sw_name VARCHAR(256),
sw_ifindex VARCHAR(256)
) WITHOUT OIDS;
--
-- v2.4.0
-- persistent interfaces
--
CREATE TABLE p_interfaces(
netdev_ip VARCHAR(256)
NOT NULL
REFERENCES netdevs(ip)
ON DELETE CASCADE
ON UPDATE CASCADE,
ifindex INT4
NOT NULL,
ifinternal INT4,
description VARCHAR(256),
alias VARCHAR(256),
-- when this interface was last known to had a netdev
last_had_netdev INT8
DEFAULT '0'
NOT NULL,
-- when this interface was last found.
ts INT8
DEFAULT '0'
NOT NULL,
PRIMARY KEY(netdev_ip, ifindex)
) WITHOUT OIDS;
CREATE TABLE reg_persons (
id VARCHAR(256)
PRIMARY KEY,
fname VARCHAR(256)
NOT NULL,
sname VARCHAR(256)
NOT NULL,
description TEXT
) WITHOUT OIDS;
CREATE TABLE reg_ips (
ip VARCHAR(256)
PRIMARY KEY,
reged_macs INTEGER
DEFAULT '0',
reged_ifs INTEGER
DEFAULT '0',
personid VARCHAR(256)
REFERENCES reg_persons(id)
ON UPDATE CASCADE
ON DELETE SET NULL,
shortdesc VARCHAR(256),
description TEXT
) WITHOUT OIDS;
CREATE TABLE reg_macs (
mac VARCHAR(256)
PRIMARY KEY,
reged_ips INTEGER
DEFAULT '0',
reged_ifs INTEGER
DEFAULT '0',
personid VARCHAR(256)
REFERENCES reg_persons(id)
ON UPDATE CASCADE
ON DELETE SET NULL,
shortdesc VARCHAR(256),
description TEXT
) WITHOUT OIDS;
CREATE TABLE reg_ifaces(
netdev_ip VARCHAR(256),
ifindex INT4,
reged_ips INTEGER
DEFAULT '0',
reged_macs INTEGER
DEFAULT '0',
personid VARCHAR(256)
REFERENCES reg_persons(id)
ON UPDATE CASCADE
ON DELETE SET NULL,
shortdesc VARCHAR(256),
description TEXT,
do_locking INTEGER
DEFAULT '0',
PRIMARY KEY(netdev_ip,ifindex),
FOREIGN KEY(netdev_ip,ifindex)
REFERENCES p_interfaces(netdev_ip, ifindex)
ON DELETE CASCADE
ON UPDATE CASCADE
) WITHOUT OIDS;
CREATE TABLE reg_ip2mac (
-- ip VARCHAR(256)
ip INET
NOT NULL,
mac VARCHAR(256)
NOT NULL,
PRIMARY KEY (ip,mac)
) WITHOUT OIDS;
CREATE TABLE reg_ip2iface (
-- ip VARCHAR(256)
ip INET
NOT NULL,
netdev_ip VARCHAR(256)
NOT NULL,
ifindex INT4
NOT NULL,
PRIMARY KEY (ip,netdev_ip,ifindex),
FOREIGN KEY(netdev_ip,ifindex)
REFERENCES p_interfaces(netdev_ip, ifindex)
ON DELETE CASCADE
ON UPDATE CASCADE
) WITHOUT OIDS;
CREATE TABLE reg_mac2iface (
mac VARCHAR(256)
NOT NULL,
netdev_ip VARCHAR(256)
NOT NULL,
ifindex INT4
NOT NULL,
PRIMARY KEY (mac,netdev_ip,ifindex),
FOREIGN KEY(netdev_ip,ifindex)
REFERENCES p_interfaces(netdev_ip, ifindex)
ON DELETE CASCADE
ON UPDATE CASCADE
) WITHOUT OIDS;
CREATE TABLE blacklist (
mac VARCHAR(256)
NOT NULL
PRIMARY KEY,
-- REFERENCES reg_macs(mac)
-- ON DELETE CASCADE
-- ON UPDATE CASCADE,
ts INT8
NOT NULL
DEFAULT EXTRACT(EPOCH FROM CURRENT_TIMESTAMP),
reason TEXT
-- ,
-- PRIMARY KEY (mac,ts)
) WITHOUT OIDS;
CREATE SEQUENCE seq_ml_log;
CREATE TABLE ml_log(
id INT4
PRIMARY KEY
DEFAULT NEXTVAL('seq_ml_log'),
ts INT8
NOT NULL
DEFAULT EXTRACT(EPOCH FROM CURRENT_TIMESTAMP),
severity INT4
NOT NULL
DEFAULT 10,
msg TEXT
NOT NULL
) WITHOUT OIDS;
CREATE TABLE ml_devs(
netdev_ip VARCHAR(256)
PRIMARY KEY
REFERENCES netdevs(ip)
ON DELETE CASCADE
ON UPDATE CASCADE,
uname VARCHAR(256),
t_pass VARCHAR(256),
en_pass VARCHAR(256),
do_locking INT4
DEFAULT 0,
last_update INT8,
last_try INT8
) WITHOUT OIDS;
CREATE VIEW view_macs AS
SELECT macs.mac AS mac,
macs.netdev_ip AS sw_ip,
macs.ifindex AS sw_ifindex,
netdevs.name AS sw_name,
interfaces.description AS sw_ifdescr,
interfaces.alias AS sw_ifalias
FROM macs, interfaces, netdevs
WHERE macs.netdev_ip = netdevs.ip AND
macs.netdev_ip = interfaces.netdev_ip AND
macs.ifindex = interfaces.ifindex;
CREATE VIEW view_ips AS
SELECT ips.ip AS ip,
ips.mac AS mac,
netdevs.name AS router_name,
netdevs.ip AS router_ip,
interfaces.ifindex AS router_ifindex,
interfaces.description AS router_ifdescr,
interfaces.alias AS router_ifalias
FROM ips, netdevs, interfaces
WHERE ips.netdev_ip = netdevs.ip AND
interfaces.netdev_ip = netdevs.ip AND
ips.ifindex = interfaces.ifindex;
CREATE VIEW view_all_pre AS
SELECT i.ip AS ip,
mac AS mac,
i.router_ip AS router_ip,
i.router_name AS router_name,
i.router_ifindex AS router_ifindex,
i.router_ifdescr AS router_ifdescr,
i.router_ifalias AS router_ifalias,
m.sw_ip AS sw_ip,
m.sw_name AS sw_name,
m.sw_ifindex AS sw_ifindex,
m.sw_ifdescr AS sw_ifdescr,
m.sw_ifalias AS sw_ifalias
FROM view_ips i FULL JOIN view_macs m
USING(mac);
CREATE VIEW view_all AS
SELECT ip, mac, router_ip, router_name, router_ifindex, router_ifdescr,
router_ifalias, sw_ip, sw_name, sw_ifindex, sw_ifdescr, sw_ifalias,
vendors.name AS mac_name
FROM view_all_pre LEFT OUTER JOIN vendors
ON vendors.prefix = substr(mac,1,8);
CREATE VIEW view_history AS
SELECT id, ts, last_ts, ip, mac, router_ip, router_name, router_ifindex,
router_ifdescr, router_ifalias, sw_ip, sw_name, sw_ifindex, sw_ifdescr,
sw_ifalias, vendors.name AS mac_name
FROM history LEFT OUTER JOIN vendors
ON vendors.prefix = substr(mac,1,8);
CREATE VIEW view_history_not_ignored AS
SELECT * FROM view_history h
WHERE NOT EXISTS
( SELECT * FROM history_ignore i
WHERE ( i.router_name IS NULL OR i.router_name='' OR
i.router_name=h.router_name ) AND
( i.router_ifindex IS NULL OR
i.router_ifindex='' OR i.router_ifindex=h.router_ifindex ) AND
( i.sw_name IS NULL OR i.sw_name='' OR
i.sw_name=h.sw_name ) AND
( i.sw_ifindex IS NULL OR i.sw_ifindex='' OR
i.sw_ifindex=h.sw_ifindex ) AND
( i.ip IS NULL OR i.ip='' OR
i.ip=substring(h.ip from 1 for octet_length(i.ip))) AND
( i.mac IS NULL OR i.mac='' OR
i.mac=substring(h.mac from 1 for octet_length(i.mac))) );
-- Same as view_history_not_ignore but don't include
-- entries with state ignored
CREATE VIEW view_history_not_ignore_state AS
SELECT * FROM view_history_not_ignored h LEFT JOIN history_state hs
ON h.id=hs.hist_id
WHERE NOT EXISTS
( SELECT * FROM history_state hs
WHERE h.id = hs.hist_id AND
h.last_ts <= hs.last_ignore );
CREATE VIEW view_stated AS
SELECT * FROM view_history_not_ignored h JOIN history_state hs
ON h.id=hs.hist_id;
--CREATE VIEW view_hist AS
-- SELECT ip, mac, sw_ip, sw_ifindex, ts, last_ts FROM history;
-- position change
CREATE VIEW view_hist_ip_mac_cnt AS
SELECT ip, mac, count(*) FROM
( SELECT ip, mac, last_ts FROM view_history_not_ignored
GROUP BY ip, mac, last_ts ) lala
GROUP BY ip,mac;
-- mac change
CREATE VIEW view_hist_ip_cnt AS
SELECT ip, count(*) FROM
( SELECT DISTINCT ip, mac
FROM view_history_not_ignored ) koko
GROUP BY ip;
-- ip change
CREATE VIEW view_hist_mac_cnt AS
SELECT mac, count(*) FROM
( SELECT DISTINCT ip, mac
FROM view_history_not_ignored ) koko
GROUP BY mac;
-- position change (without ignored)
CREATE VIEW view_hist_ip_mac_cnt_state AS
SELECT ip, mac, count(*) FROM
( SELECT ip, mac, last_ts FROM view_history_not_ignore_state
GROUP BY ip, mac, last_ts ) lala
GROUP BY ip,mac;
-- mac change (without ignored)
CREATE VIEW view_hist_ip_cnt_state AS
SELECT ip, count(*) FROM
( SELECT DISTINCT ip, mac
FROM view_history_not_ignore_state ) koko
GROUP BY ip;
-- ip change (without ignored)
CREATE VIEW view_hist_mac_cnt_state AS
SELECT mac, count(*) FROM
( SELECT DISTINCT ip, mac
FROM view_history_not_ignore_state ) koko
GROUP BY mac;
-- view_all with ip and mac registries
--CREATE VIEW view_all_reg AS
-- SELECT ip, a.mac, router_ip, router_name, router_ifindex, router_ifdescr,
-- router_ifalias, sw_ip, sw_name, sw_ifindex, sw_ifdescr, sw_ifalias,
-- mac_name, reg_ip_ip, ip_personid, reged_macs, ip_shortdesc,
-- reg_macs.mac AS reg_mac_mac, reg_macs.personid AS mac_personid,
-- reged_ips, reg_macs.shortdesc AS mac_shortdesc FROM
-- ( SELECT view_all.ip, mac, router_ip, router_name,
router_ifindex, router_ifdescr,
-- router_ifalias, sw_ip, sw_name, sw_ifindex,
sw_ifdescr, sw_ifalias,
-- mac_name, personid AS ip_personid, reged_macs,
shortdesc AS ip_shortdesc,
-- reg_ips.ip AS reg_ip_ip
-- FROM view_all LEFT JOIN reg_ips
-- ON view_all.ip=reg_ips.ip ) AS a LEFT
JOIN reg_macs
-- ON a.mac=reg_macs.mac;
--CREATE VIEW view_history_reg AS
-- SELECT id, ts, last_ts, ip, a.mac, router_ip, router_name, router_ifindex,
-- router_ifdescr, router_ifalias, sw_ip, sw_name, sw_ifindex, sw_ifdescr,
-- sw_ifalias, mac_name, reg_ip_ip, ip_personid, reged_macs, ip_shortdesc,
-- reg_macs.mac AS reg_mac_mac, reg_macs.personid AS mac_personid,
-- reged_ips, reg_macs.shortdesc AS mac_shortdesc FROM
-- ( SELECT id, ts, last_ts, view_history.ip, mac, router_ip,
router_name, router_ifindex,
-- router_ifdescr, router_ifalias, sw_ip, sw_name,
sw_ifindex, sw_ifdescr,
-- sw_ifalias, mac_name, personid AS ip_personid,
reged_macs,
-- shortdesc AS ip_shortdesc, reg_ips.ip AS reg_ip_ip
-- FROM view_history LEFT JOIN reg_ips
-- ON view_history.ip=reg_ips.ip ) AS a
LEFT JOIN reg_macs
-- ON a.mac=reg_macs.mac;
CREATE VIEW view_history_reg AS
SELECT v.ip, v.mac,
id, ts, last_ts, router_ip, router_name, router_ifindex,
router_ifdescr, router_ifalias,
sw_ip, sw_name, sw_ifindex, sw_ifdescr, sw_ifalias, mac_name,
i.reged_macs AS ip_reged_macs, i.reged_ifs AS ip_reged_ifs,
m.reged_ips AS mac_reged_ips, m.reged_ifs AS mac_reged_ifs,
f.reged_ips AS if_reged_ips, f.reged_macs AS if_reged_macs,
( SELECT 1 WHERE EXISTS ( SELECT * FROM reg_ip2mac ii WHERE
ii.ip>>=INET(v.ip) AND ii.mac=v.mac ) ) AS i2m_assoc,
( SELECT 1 WHERE EXISTS ( SELECT * FROM reg_ip2iface ii WHERE
ii.ip>>=INET(v.ip) AND ii.ifindex=v.sw_ifindex AND ii.netdev_ip=v.sw_ip ) ) AS
i2f_assoc,
( SELECT 1 WHERE EXISTS ( SELECT * FROM reg_mac2iface ii WHERE
ii.mac=v.mac AND ii.ifindex=v.sw_ifindex AND ii.netdev_ip=v.sw_ip ) ) AS m2f_assoc,
( SELECT 1 WHERE i.ip IS NOT NULL ) AS ip_is_reg,
( SELECT 1 WHERE m.mac IS NOT NULL ) AS mac_is_reg,
( SELECT 1 WHERE f.netdev_ip IS NOT NULL ) AS if_is_reg,
i.shortdesc AS ip_shortdesc, m.shortdesc AS mac_shortdesc, f.shortdesc
AS if_shortdesc
FROM view_history v
LEFT JOIN reg_ips i ON INET(v.ip)<<=INET(i.ip)
LEFT JOIN reg_macs m ON v.mac=m.mac
LEFT JOIN reg_ifaces f ON ( v.sw_ip=f.netdev_ip AND
v.sw_ifindex=f.ifindex )
LEFT JOIN reg_ip2mac i2m ON ( INET(v.ip)<<=i2m.ip AND
v.mac=i2m.mac )
LEFT JOIN reg_ip2iface i2f ON ( INET(v.ip)<<=i2f.ip AND
i2f.ifindex=v.sw_ifindex AND i2f.netdev_ip=v.sw_ip )
LEFT JOIN reg_mac2iface m2f ON ( v.mac=m2f.mac AND
m2f.ifindex=v.sw_ifindex AND m2f.netdev_ip=v.sw_ip )
;
CREATE VIEW view_all_reg AS
SELECT v.ip, v.mac,
router_ip, router_name, router_ifindex, router_ifdescr, router_ifalias,
sw_ip, sw_name, sw_ifindex, sw_ifdescr, sw_ifalias, mac_name,
i.reged_macs AS ip_reged_macs, i.reged_ifs AS ip_reged_ifs,
m.reged_ips AS mac_reged_ips, m.reged_ifs AS mac_reged_ifs,
f.reged_ips AS if_reged_ips, f.reged_macs AS if_reged_macs,
( SELECT 1 WHERE EXISTS ( SELECT * FROM reg_ip2mac ii WHERE
ii.ip>>=INET(v.ip) AND ii.mac=v.mac ) ) AS i2m_assoc,
( SELECT 1 WHERE EXISTS ( SELECT * FROM reg_ip2iface ii WHERE
ii.ip>>=INET(v.ip) AND ii.ifindex=v.sw_ifindex AND ii.netdev_ip=v.sw_ip ) ) AS
i2f_assoc,
( SELECT 1 WHERE EXISTS ( SELECT * FROM reg_mac2iface ii WHERE
ii.mac=v.mac AND ii.ifindex=v.sw_ifindex AND ii.netdev_ip=v.sw_ip ) ) AS m2f_assoc,
( SELECT 1 WHERE i.ip IS NOT NULL ) AS ip_is_reg,
( SELECT 1 WHERE m.mac IS NOT NULL ) AS mac_is_reg,
( SELECT 1 WHERE f.netdev_ip IS NOT NULL ) AS if_is_reg,
i.shortdesc AS ip_shortdesc, m.shortdesc AS mac_shortdesc, f.shortdesc
AS if_shortdesc,
f.do_locking AS if_do_locking
FROM view_all v
LEFT JOIN reg_ips i ON INET(v.ip)<<=INET(i.ip)
LEFT JOIN reg_macs m ON v.mac=m.mac
LEFT JOIN reg_ifaces f ON ( v.sw_ip=f.netdev_ip AND
v.sw_ifindex=f.ifindex )
LEFT JOIN reg_ip2mac i2m ON ( i2m.ip>>=INET(v.ip) AND
v.mac=i2m.mac )
LEFT JOIN reg_ip2iface i2f ON ( i2f.ip>>=INET(v.ip) AND
i2f.ifindex=v.sw_ifindex AND i2f.netdev_ip=v.sw_ip )
LEFT JOIN reg_mac2iface m2f ON ( v.mac=m2f.mac AND
m2f.ifindex=v.sw_ifindex AND m2f.netdev_ip=v.sw_ip )
;
CREATE VIEW view_err AS
SELECT * FROM view_all_reg WHERE
sw_ip IS NOT NULL AND
sw_ip <> '' AND
mac IS NOT NULL AND
if_do_locking = 1 AND (
( mac IS NOT NULL AND
m2f_assoc IS NULL AND
( mac_reged_ifs = 1 OR
if_reged_macs = 1 ) ) OR
( ip IS NOT NULL AND
i2f_assoc IS NULL AND
( ip_reged_ifs = 1 OR
if_reged_ips = 1 ) ) OR
( ip IS NOT NULL AND
mac IS NOT NULL AND
i2m_assoc IS NULL AND
( ip_reged_macs = 1 OR
mac_reged_ips = 1 ) ) )
;
CREATE VIEW view_locks AS
SELECT p.netdev_ip AS sw_ip, p.ifindex AS ifindex,
p.description AS ifdescr, m2f.mac AS mac
FROM p_interfaces p, reg_ifaces i
LEFT JOIN reg_mac2iface m2f ON (
m2f.netdev_ip = i.netdev_ip AND m2f.ifindex = i.ifindex )
WHERE p.netdev_ip = i.netdev_ip AND
p.ifindex = i.ifindex AND
i.do_locking = '1' AND
NOT EXISTS (
SELECT * FROM blacklist bl
WHERE bl.mac=m2f.mac )
;
-- Views for locating good associations
CREATE VIEW view_t_i2m AS
SELECT DISTINCT ip, mac
FROM history h
WHERE
(SELECT count(*)
FROM ( SELECT DISTINCT ip
FROM history h2
WHERE mac=h.mac ) AS a
) = 1 AND
(SELECT count(*)
FROM ( SELECT DISTINCT mac
FROM history h2
WHERE ip=h.ip ) AS a
) = 1;
CREATE VIEW view_t_i2m_not AS
SELECT DISTINCT ip,mac
FROM history h
EXCEPT SELECT ip,mac
FROM view_t_i2m;
CREATE VIEW view_t_i2f AS
SELECT DISTINCT ip, sw_ip, sw_ifindex
FROM history h
WHERE
(SELECT count(*)
FROM ( SELECT DISTINCT sw_ip, sw_ifindex
FROM history h2
WHERE ip=h.ip ) AS a
) = 1 AND
sw_ifindex IS NOT NULL;
CREATE VIEW view_t_i2f_not AS
SELECT DISTINCT ip, sw_ip, sw_ifindex
FROM history h
WHERE sw_ifindex IS NOT NULL
EXCEPT SELECT ip, sw_ip, sw_ifindex
FROM view_t_i2f;
CREATE VIEW view_t_m2f AS
SELECT DISTINCT mac, sw_ip, sw_ifindex
FROM history h
WHERE
(SELECT count(*)
FROM ( SELECT DISTINCT sw_ip, sw_ifindex
FROM history h2
WHERE mac=h.mac ) AS a
) = 1 AND
sw_ifindex IS NOT NULL;
CREATE VIEW view_t_m2f_not AS
SELECT DISTINCT mac, sw_ip, sw_ifindex
FROM history h
WHERE sw_ifindex IS NOT NULL
EXCEPT SELECT mac, sw_ip, sw_ifindex
FROM view_t_m2f;
CREATE VIEW view_lockable_interfaces AS
SELECT * FROM netdevs n, p_interfaces p
WHERE n.dev_type=2 AND
n.ip=p.netdev_ip AND
( p.description LIKE 'Fast%' OR
p.description LIKE 'Giga%' );
CREATE VIEW view_lock_interfaces AS
SELECT ip, name, tot_ifs, lockable_ifs, netdev_ifs,
locked_ifs, uname, t_pass, en_pass,
do_locking, last_update, last_try
FROM
( SELECT ip, name, count(*) AS tot_ifs
FROM netdevs n, p_interfaces p
WHERE n.dev_type=2 AND
n.ip=p.netdev_ip
GROUP BY ip,name ) AS a
LEFT JOIN
( SELECT ip, count(*) AS lockable_ifs
FROM view_lockable_interfaces v
GROUP BY ip ) AS b USING(ip)
LEFT JOIN
( SELECT ip, count(*) AS netdev_ifs
FROM view_lockable_interfaces v
WHERE v.last_had_netdev>0
GROUP BY ip ) AS c USING(ip)
LEFT JOIN
( SELECT ip, count(*) AS locked_ifs
FROM view_lockable_interfaces v,
reg_ifaces rif
WHERE v.netdev_ip=rif.netdev_ip AND
v.ifindex=rif.ifindex AND
rif.do_locking=1
GROUP BY ip) AS d USING(ip)
LEFT JOIN ml_devs m ON a.ip=m.netdev_ip
;
CREATE VIEW view_lock_interface AS
SELECT p.netdev_ip, p.ifindex, p.description, p.alias,
( SELECT 1 WHERE p.last_had_netdev IS NOT NULL AND p.last_had_netdev >
0 ) AS has_netdev,
r.do_locking,
( SELECT 1 WHERE r.ifindex IS NOT NULL ) AS reged_if,
( SELECT COUNT(DISTINCT mac) FROM macs m WHERE
m.netdev_ip=p.netdev_ip AND m.ifindex=p.ifindex ) AS last_devs,
( SELECT COUNT(DISTINCT mac) FROM history h WHERE
h.sw_ip=p.netdev_ip AND h.sw_ifindex=p.ifindex ) AS hist_devs,
( SELECT COUNT(*) FROM reg_ip2iface r WHERE
r.netdev_ip=p.netdev_ip AND r.ifindex=p.ifindex) AS ip_assocs,
( SELECT COUNT(*) FROM reg_mac2iface r WHERE
r.netdev_ip=p.netdev_ip AND r.ifindex=p.ifindex) AS mac_assocs
FROM p_interfaces p
LEFT JOIN reg_ifaces r
ON p.ifindex=r.ifindex AND p.netdev_ip=r.netdev_ip;
-- Devices that are candidates for locking
-- is_old == 1 if the device was last set more than 32 hours ago
CREATE VIEW view_ml_tolock AS
SELECT *,
( SELECT 1 WHERE
( ((EXTRACT(EPOCH FROM CURRENT_TIMESTAMP)) - last_try) >
115200) OR
last_try IS NULL ) AS is_old
FROM ml_devs
WHERE ( t_pass IS NOT NULL AND
en_pass IS NOT NULL AND
t_pass <> '' AND
en_pass <> '' ) AND
do_locking=1;
--
-- ip,mac
-- +--- not exist -> INSERT
-- |
-- +--- exist
-- +--- old sw_ip is NULL -> UPDATE (delete & insert)
-- |
-- +--- old sw_ip is NOT NULL
-- +-- new sw_ip is NULL -> do nothing
-- |
-- +-- new sw_ip is NOT NULL
-- +-- old sw_ip == new sw_ip AND
-- | old sw_ifindex == new sw_ifindex -> UPDATE last_ts
-- |
-- +-- old sw_ip != new sw_ip OR
-- old sw_ifindex != new sw_ifindex -> INSERT
--
--
--v2.4.0: Don't insert entries reported for interfaces which were known
-- to have netdevs (from p_interfaces)
--
--
--
--
--
CREATE OR REPLACE FUNCTION set_history()
RETURNS INT4
AS '
-- Delete old entries with unknown switch ip that are
-- now known
DELETE FROM history
WHERE history.sw_ip IS NULL AND
EXISTS ( SELECT * FROM view_all v
WHERE history.ip = v.ip AND
history.mac = v.mac AND
v.sw_ip IS NOT NULL );
-- Delete old entries with unknown ip that are now known
DELETE FROM history
WHERE history.ip IS NULL AND
EXISTS ( SELECT * FROM view_all v
WHERE history.mac=v.mac AND
v.ip IS NOT NULL );
-- Insert New entries
INSERT INTO
history(ip,mac,router_ip,router_name,router_ifindex,router_ifdescr,router_ifalias,sw_ip,
sw_name,sw_ifindex,sw_ifdescr,sw_ifalias)
SELECT
ip,mac,router_ip,router_name,router_ifindex,router_ifdescr,router_ifalias,
sw_ip,sw_name,sw_ifindex,sw_ifdescr,sw_ifalias
FROM view_all v
WHERE
-- ip IS NOT NULL AND
-- mac IS NOT NULL AND
-- on interfaces where there was never a netdev
( NOT EXISTS (
SELECT last_had_netdev FROM p_interfaces p
WHERE p.netdev_ip=v.sw_ip AND
p.ifindex=v.sw_ifindex AND
p.last_had_netdev > 0 ) ) AND
-- and there is no same history entry
( NOT EXISTS ( SELECT * FROM history h
WHERE ( h.ip = v.ip OR ( h.ip
IS NULL AND v.ip IS NULL ) ) AND
( h.mac = v.mac OR (
h.mac IS NULL AND v.mac IS NULL ) ) AND
( h.sw_ip = v.sw_ip OR
( h.sw_ip IS NULL AND v.sw_ip IS NULL ) ) AND
( h.sw_ifindex =
v.sw_ifindex OR ( h.sw_ifindex IS NULL AND v.sw_ifindex IS NULL ) )
) ) AND
-- and we know more info than we did (if it not a change)
-- if sw_ip IS NULL and ip/mac already exists dont add it (ip/mac cannot be null
in that case)
( v.sw_ip IS NOT NULL OR
( NOT EXISTS ( SELECT * FROM history h
WHERE h.ip = v.ip AND
h.mac = v.mac )
) ) AND
-- if ip IS NULL and mac/sw_ip/sw_ifindex already exists dont add it (
mac/sw_ip/sw_ifindex cannot be null )
( v.ip IS NOT NULL OR
( NOT EXISTS ( SELECT * FROM history h
WHERE h.mac = v.mac AND
h.sw_ip = v.sw_ip AND
h.sw_ifindex = v.sw_ifindex )
) )
;
-- AND
-- and:
-- there is a history entry with different sw_ip/sw_ifindex
-- ( EXISTS ( SELECT * FROM history h
-- WHERE ( h.ip = v.ip OR ( h.ip IS NULL
AND v.ip IS NULL ) ) AND
-- ( h.mac = v.mac OR ( h.mac IS
NULL AND v.mac IS NULL ) ) AND
-- h.sw_ip IS NOT NULL AND
-- ( h.sw_ip <> v.sw_ip OR
-- h.sw_ifindex <> v.sw_ifindex )
AND
-- v.sw_ip IS NOT NULL ) );
-- and no same entry exists
-- Update existing entries
UPDATE history SET last_ts = EXTRACT(EPOCH FROM CURRENT_TIMESTAMP)
WHERE history.sw_ip IS NOT NULL AND
EXISTS ( SELECT * FROM view_all v
WHERE ( v.ip = history.ip OR ( v.ip IS
NULL AND history.ip IS NULL ) ) AND
( v.mac = history.mac OR (
v.mac IS NULL AND history.mac IS NULL ) ) AND
v.sw_ip = history.sw_ip AND
v.sw_ifindex =
history.sw_ifindex );
SELECT 1;
'
LANGUAGE SQL;
-- Remove data that are older than a week
CREATE OR REPLACE FUNCTION expire_history()
RETURNS INT4
AS '
DELETE FROM history
WHERE last_ts < ( EXTRACT(EPOCH FROM CURRENT_TIMESTAMP) -
604800 );
SELECT 1;
'
LANGUAGE SQL;
-- Remove reg_ip2mac entries that have no reged ip and no reged mac
CREATE OR REPLACE FUNCTION fix_ip2mac_ip_del()
RETURNS OPAQUE
AS '
BEGIN
DELETE FROM reg_ip2mac
WHERE reg_ip2mac.ip<<=INET(OLD.ip) AND
NOT EXISTS (
SELECT * FROM reg_macs m
WHERE reg_ip2mac.mac=m.mac ) AND
NOT EXISTS (
SELECT * FROM reg_ips i
WHERE reg_ip2mac.ip<<=INET(i.ip) );
RETURN OLD;
END
'
LANGUAGE 'plpgsql';
CREATE OR REPLACE FUNCTION fix_ip2mac_mac_del()
RETURNS OPAQUE
AS '
BEGIN
DELETE FROM reg_ip2mac
WHERE reg_ip2mac.mac=OLD.mac AND
NOT EXISTS (
SELECT * FROM reg_ips i
WHERE reg_ip2mac.ip<<=INET(i.ip) );
RETURN OLD;
END
'
LANGUAGE 'plpgsql';
-- Generic fix - not called by a trigger
CREATE OR REPLACE FUNCTION fix_ip2mac()
RETURNS INTEGER
AS '
BEGIN
-- TODO: Enable those
DELETE FROM reg_ip2mac
WHERE NOT EXISTS (
SELECT * FROM reg_ips i
WHERE reg_ip2mac.ip<<=INET(i.ip) ) AND
NOT EXISTS (
SELECT * FROM reg_macs m
WHERE reg_ip2mac.mac=m.mac );
RETURN 1;
END
'
LANGUAGE 'plpgsql';
-- When updating reg_ips or reg_macs also update reg_ip2mac
CREATE OR REPLACE FUNCTION fix_ip2mac_ip_upd()
RETURNS OPAQUE
AS '
BEGIN
UPDATE reg_ip2mac
SET ip=INET(NEW.ip)
WHERE ip=OLD.ip;
RETURN NEW;
END
'
LANGUAGE 'plpgsql';
CREATE OR REPLACE FUNCTION fix_ip2mac_mac_upd()
RETURNS OPAQUE
AS '
BEGIN
UPDATE reg_ip2mac
SET mac=NEW.mac
WHERE mac=OLD.mac;
RETURN NEW;
END
'
LANGUAGE 'plpgsql';
-- Auto run the above function
CREATE TRIGGER trig_fix_del AFTER DELETE
ON reg_ips FOR EACH ROW
EXECUTE PROCEDURE fix_ip2mac_ip_del();
CREATE TRIGGER trig_fix_del AFTER DELETE
ON reg_macs FOR EACH ROW
EXECUTE PROCEDURE fix_ip2mac_mac_del();
CREATE TRIGGER trig_fix_upd AFTER UPDATE
ON reg_ips FOR EACH ROW
EXECUTE PROCEDURE fix_ip2mac_ip_upd();
CREATE TRIGGER trig_fix_upd AFTER UPDATE
ON reg_macs FOR EACH ROW
EXECUTE PROCEDURE fix_ip2mac_mac_upd();
--
-- Set last_found when an interface is updated
--
CREATE OR REPLACE FUNCTION set_last_found()
RETURNS OPAQUE
AS '
BEGIN
-- Reset first found if device was not updated for 5 days
UPDATE netdevs
SET first_found=EXTRACT(EPOCH FROM CURRENT_TIMESTAMP)
WHERE ip=NEW.netdev_ip AND
( EXTRACT(EPOCH FROM CURRENT_TIMESTAMP) - last_found )
> 432000;
UPDATE netdevs
SET last_found=EXTRACT(EPOCH FROM CURRENT_TIMESTAMP)
WHERE ip=NEW.netdev_ip;
RETURN NEW;
END
'
LANGUAGE 'plpgsql';
CREATE TRIGGER trig_set_last_found
AFTER INSERT OR UPDATE
ON interfaces
FOR EACH ROW EXECUTE PROCEDURE set_last_found();
-- update p_interfaces as needed
CREATE OR REPLACE FUNCTION set_piface()
RETURNS INTEGER
AS '
BEGIN
-- delete changed interfaces and interfaces older than 5 days
DELETE FROM p_interfaces
WHERE EXISTS (
SELECT * FROM interfaces i
WHERE i.netdev_ip = p_interfaces.netdev_ip AND
i.ifindex = p_interfaces.ifindex AND
( (
-- If has_netdev changed from 0 to 1 , then this interface has changed
i.has_netdev=1 AND
p_interfaces.last_had_netdev<p_interfaces.ts
) OR
-- If alias chaqnged
-- i.alias<>p_interfaces.alias
-- OR
-- If description changed
i.description<>p_interfaces.description
) ) OR
( (EXTRACT(EPOCH FROM CURRENT_TIMESTAMP) -
p_interfaces.ts) > 432000) OR
-- If this is not a netdev interface any more (5 days)
( p_interfaces.last_had_netdev > 10 AND
( EXTRACT(EPOCH FROM CURRENT_TIMESTAMP) -
p_interfaces.last_had_netdev ) > 432000 );
-- If alias changed do not perform locking any more
UPDATE reg_ifaces
SET do_locking=0
WHERE EXISTS (
SELECT * FROM interfaces i, p_interfaces p
WHERE i.netdev_ip = p.netdev_ip AND
i.ifindex = p.ifindex AND
i.netdev_ip = reg_ifaces.netdev_ip AND
i.ifindex = reg_ifaces.ifindex AND (
( i.alias IS NULL AND p.alias IS NOT
NULL AND p.alias<>'' ) OR
( p.alias IS NULL AND i.alias IS NOT
NULL AND i.alias<>'' ) OR
( i.alias IS NOT NULL AND p.alias IS
NOT NULL AND i.alias <> p.alias ) ) );
-- insert non-existent interfaces into p_interfaces
INSERT INTO p_interfaces(netdev_ip, ifindex, ifinternal, description,
alias)
SELECT netdev_ip, ifindex, ifinternal, description, alias
FROM interfaces i
WHERE NOT EXISTS (
SELECT * FROM p_interfaces
WHERE netdev_ip=i.netdev_ip AND
ifindex=i.ifindex) AND
ifinternal<>-1;
-- update last_found
UPDATE p_interfaces
SET ts=EXTRACT(EPOCH FROM CURRENT_TIMESTAMP)
WHERE EXISTS (
SELECT * FROM interfaces i
WHERE i.netdev_ip=p_interfaces.netdev_ip AND
i.ifindex=p_interfaces.ifindex );
-- update last_had_netdev
-- this has to be done AFTER updating last_found to prevent last_had_netdev<last_found
UPDATE p_interfaces
SET last_had_netdev=EXTRACT(EPOCH FROM CURRENT_TIMESTAMP)
WHERE EXISTS (
SELECT * FROM interfaces i
WHERE i.netdev_ip=p_interfaces.netdev_ip AND
i.ifindex=p_interfaces.ifindex AND
i.has_netdev>0 );
-- update alias
UPDATE p_interfaces
SET alias=(
SELECT alias FROM interfaces i
WHERE i.netdev_ip=p_interfaces.netdev_ip AND
i.ifindex=p_interfaces.ifindex )
WHERE ( alias<>(
SELECT alias FROM interfaces i
WHERE i.netdev_ip=p_interfaces.netdev_ip AND
i.ifindex=p_interfaces.ifindex ) );
RETURN 1;
END
'
LANGUAGE 'plpgsql';
CREATE OR REPLACE FUNCTION update_blacklist()
RETURNS INTEGER
AS '
BEGIN
INSERT INTO blacklist(mac,reason)
SELECT mac, \'(auto) MAC-Interface mismatch\' FROM view_err v
WHERE NOT EXISTS ( SELECT * FROM blacklist b WHERE
v.mac=b.mac ) AND
( v.mac IS NOT NULL AND v.m2f_assoc IS NULL AND
( v.mac_reged_ifs = 1 OR
v.if_reged_macs = 1 ) );
-- AND
-- EXISTS ( SELECT * FROM reg_macs r WHERE
r.mac=v.mac) );
INSERT INTO blacklist(mac,reason)
SELECT mac, \'(auto) IP-Interface mismatch\' FROM view_err v
WHERE NOT EXISTS ( SELECT * FROM blacklist b WHERE
v.mac=b.mac ) AND
( v.ip IS NOT NULL AND v.i2f_assoc IS NULL AND
( v.ip_reged_ifs = 1 OR v.if_reged_ips
= 1 ) );
-- AND
-- EXISTS ( SELECT * FROM reg_macs r WHERE
r.mac=v.mac) );
INSERT INTO blacklist(mac,reason)
SELECT mac, \'(auto) IP-MAC mismatch\' FROM view_err v
WHERE NOT EXISTS ( SELECT * FROM blacklist b WHERE
v.mac=b.mac ) AND
( v.ip IS NOT NULL AND v.mac IS NOT NULL AND
v.i2m_assoc IS NULL AND
( v.ip_reged_macs = 1 OR
v.mac_reged_ips = 1 ) );
-- AND
-- EXISTS ( SELECT * FROM reg_macs r WHERE
r.mac=v.mac) );
RETURN 1;
END
'
LANGUAGE 'plpgsql';
CREATE OR REPLACE FUNCTION set_good_assoc()
RETURNS INTEGER
AS '
BEGIN
INSERT INTO reg_ip2mac(ip,mac)
SELECT INET(ip),mac FROM (
SELECT INET(ip) AS ip,mac FROM view_t_i2m
EXCEPT SELECT ip,mac FROM reg_ip2mac ) AS a;
INSERT INTO reg_ip2iface(ip, netdev_ip, ifindex)
SELECT INET(ip), sw_ip, sw_ifindex FROM (
SELECT INET(ip) AS ip, sw_ip, sw_ifindex FROM
view_t_i2f
EXCEPT SELECT ip, netdev_ip, ifindex FROM
reg_ip2iface ) AS a;
INSERT INTO reg_mac2iface(mac, netdev_ip, ifindex)
SELECT mac, sw_ip, sw_ifindex FROM (
SELECT mac, sw_ip, sw_ifindex FROM view_t_m2f
EXCEPT SELECT mac, netdev_ip, ifindex FROM
reg_mac2iface ) AS a;
RETURN 1;
END
'
LANGUAGE 'plpgsql';
--CREATE OR REPLACE FUNCTION trig_blacklist_add()
-- RETURNS OPAQUE
-- AS '
-- DECLARE
-- CNT INTEGER;
-- BEGIN
-- SELECT INTO CNT COUNT(*) FROM reg_mac2iface
-- WHERE mac=NEW.mac;
--
-- IF CNT = 0 THEN
-- RETURN NULL;
-- ELSE
-- RETURN NEW;
-- END IF;
-- END
-- '
-- LANGUAGE 'plpgsql';
--CREATE TRIGGER trig_blacklist_insert BEFORE INSERT
-- ON blacklist FOR EACH ROW
-- EXECUTE PROCEDURE trig_blacklist_add();
-- Expire log entries older than 7 days
CREATE OR REPLACE FUNCTION expire_ml_log()
RETURNS INTEGER
AS '
DELETE FROM ml_log
WHERE ts < ( EXTRACT(EPOCH FROM CURRENT_TIMESTAMP) - 604800 );
SELECT 1;
'
LANGUAGE SQL;
CREATE OR REPLACE FUNCTION set_ml_upd(VARCHAR(256))
RETURNS INTEGER
AS '
UPDATE ml_devs
SET last_update = (EXTRACT (EPOCH FROM CURRENT_TIMESTAMP))
WHERE netdev_ip = $1;
SELECT 1;
'
LANGUAGE SQL;
CREATE OR REPLACE FUNCTION set_ml_try(VARCHAR(256))
RETURNS INTEGER
AS '
UPDATE ml_devs
SET last_try = (EXTRACT (EPOCH FROM CURRENT_TIMESTAMP))
WHERE netdev_ip = $1;
SELECT 1;
'
LANGUAGE SQL;
---------------------------(end of broadcast)---------------------------
TIP 5: Have you checked our extensive FAQ?
http://www.postgresql.org/users-lounge/docs/faq.html