def session_started(con, source, mac, time, ipv4=None, ipv6=None): """Record an address session. Possibly associates the session with any corresponding user session. """ # # There's no one useful to return an error to, so we just close any # # previous open sessions, so we at least get a record that it got # # reopened. cur = con.execute('UPDATE addr_sessions SET end = ?' ' WHERE source = ? AND mac = ? AND ipv4 IS ?' ' AND ipv6 IS ? AND end IS NULL', (time, source, mac.bytes, common.ipv4_to_bytes(ipv4), common.ipv6_to_bytes(ipv6))) if cur.rowcount > 0: logger().warn(('Closed {0:d} existing {1} sessions for ' '{2!r} {3!r} {4!r}').format(cur.rowcount, source, mac, ipv4, ipv6)) cur = con.execute('SELECT id FROM user_sessions' ' WHERE mac = ? AND end IS NULL', (mac.bytes,)) row = cur.fetchone() if row: usersess = row[0] if cur.fetchone(): logger().warn('More than one user session for {0!r}'.format(mac)) else: usersess = None con.execute('INSERT INTO addr_sessions' ' (user_session, mac, source, ipv4, ipv6, start)' ' VALUES (?,?,?,?,?,?)', (usersess, mac.bytes, source, common.ipv4_to_bytes(ipv4), common.ipv6_to_bytes(ipv6), time)) logger().info(('Session from {2} started at {5!s}: {1!r} {3!r} {4!r}' ' (matched with user session {0!s})' ).format(usersess, mac, source, ipv4, ipv6, time))
def session_ended(con, source, mac, time, ipv4=None, ipv6=None): """Record a session ending. If enough of the user's address sessions have ended, terminate the user sessions and revoke their access. Current criteria: revoke if all arp and nd sessions for the mac have ended. """ # Pseudocode: # SELECT id, user_session FROM addr_sessions WHERE source = ? AND mac = ? # AND (ipv4/6 clause) # (source, mac.bytes, ipv4/6) # UPDATE addr_sessions SET end = ? WHERE id = ? # (time, id) # SELECT COUNT(*) FROM addr_sessions WHERE user_session = ? # AND source IN ('arp', 'nd') AND end IS NULL # (user_session) # if count == 0: # end_user_session(con, user_session) pass cur = con.execute('SELECT id, user_session FROM addr_sessions' ' WHERE source = ? AND mac = ?' ' AND ipv4 IS ? AND ipv6 IS ? AND end IS NULL', (source, mac.bytes, common.ipv4_to_bytes(ipv4), common.ipv6_to_bytes(ipv6))) rows = cur.fetchall() addr_sessions = [row[0] for row in rows] user_sessions = set([row[1] for row in rows]) if len(addr_sessions) > 1: logger().warn(('session_ended: More than one {0} session open for' ' {1!r} {2!r} {3!r}. Closing all of them' ).format(source, mac, ipv4, ipv6)) if len(user_sessions) > 1: logger().error('session_ended: Multiple user sessions as well.') for addrsess in addr_sessions: con.execute('UPDATE addr_sessions SET end = ? WHERE id = ?', (time, addrsess)) for usersess in user_sessions: if usersess is not None: cur = con.execute('SELECT COUNT(*) FROM addr_sessions' ' WHERE user_session = ?' ' AND source IN (\'arp\', \'nd\') AND end IS NULL', (usersess,)) if cur.fetchone()[0] == 0: end_user_session(con, usersess)