Skip to content

Commit

Permalink
add coa server support
Browse files Browse the repository at this point in the history
  • Loading branch information
Christian Giese committed Jan 30, 2017
1 parent 351124b commit db780ca
Showing 1 changed file with 74 additions and 13 deletions.
87 changes: 74 additions & 13 deletions pyrad/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class Server(host.Host):
MaxPacketSize = 8192

def __init__(self, addresses=[], authport=1812, acctport=1813, coaport=3799,
hosts=None, dict=None):
hosts=None, dict=None, auth_enabled=True, acct_enabled=True, coa_enabled=True):
"""Constructor.
:param addresses: IP addresses to listen on
Expand All @@ -88,8 +88,12 @@ def __init__(self, addresses=[], authport=1812, acctport=1813, coaport=3799,
else:
self.hosts = hosts

self.auth_enabled = auth_enabled
self.authfds = []
self.acct_enabled = acct_enabled
self.acctfds = []
self.coa_enabled = coa_enabled
self.coafds = []

for addr in addresses:
self.BindToAddress(addr)
Expand All @@ -101,16 +105,24 @@ def BindToAddress(self, addr):
:param addr: IP address to listen on
:type addr: string
"""
authfd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
authfd.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
authfd.bind((addr, self.authport))
if self.auth_enabled:
authfd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
authfd.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
authfd.bind((addr, self.authport))
self.authfds.append(authfd)

acctfd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
acctfd.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
acctfd.bind((addr, self.acctport))
if self.acct_enabled:
acctfd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
acctfd.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
acctfd.bind((addr, self.acctport))
self.acctfds.append(acctfd)

if self.coa_enabled:
coafd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
coafd.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
coafd.bind((addr, self.coaport))
self.coafds.append(coafd)

self.authfds.append(authfd)
self.acctfds.append(acctfd)

def HandleAuthPacket(self, pkt):
"""Authentication packet handler.
Expand All @@ -132,6 +144,27 @@ def HandleAcctPacket(self, pkt):
:type pkt: Packet class instance
"""

def HandleCoaPacket(self, pkt):
"""CoA packet handler.
This is an empty function that is called when a valid
accounting packet has been received. It can be overriden in
derived classes to add custom behaviour.
:param pkt: packet to process
:type pkt: Packet class instance
"""

def HandleDisconnectPacket(self, pkt):
"""CoA packet handler.
This is an empty function that is called when a valid
accounting packet has been received. It can be overriden in
derived classes to add custom behaviour.
:param pkt: packet to process
:type pkt: Packet class instance
"""


def _HandleAuthPacket(self, pkt):
"""Process a packet received on the authentication port.
If this packet should be dropped instead of processed a
Expand Down Expand Up @@ -169,6 +202,27 @@ def _HandleAcctPacket(self, pkt):
'Received non-accounting packet on accounting port')
self.HandleAcctPacket(pkt)

def _HandleCoaPacket(self, pkt):
"""Process a packet received on the coa port.
If this packet should be dropped instead of processed a
ServerPacketError exception should be raised. The main loop will
drop the packet and log the reason.
:param pkt: packet to process
:type pkt: Packet class instance
"""
if pkt.source[0] not in self.hosts:
raise ServerPacketError('Received packet from unknown host')

pkt.secret = self.hosts[pkt.source[0]].secret
if pkt.code == packet.CoARequest:
self.HandleCoaPacket(pkt)
elif pkt.code == packet.DisconnectRequest:
self.HandleDisconnectPacket(pkt)
else:
raise ServerPacketError('Received non-coa packet on coa port')


def _GrabPacket(self, pktgen, fd):
"""Read a packet from a network connection.
This method assumes there is data waiting for to be read.
Expand All @@ -187,11 +241,15 @@ def _GrabPacket(self, pktgen, fd):
def _PrepareSockets(self):
"""Prepare all sockets to receive packets.
"""
for fd in self.authfds + self.acctfds:
for fd in self.authfds + self.acctfds + self.coafds:
self._fdmap[fd.fileno()] = fd
self._poll.register(fd.fileno(), select.POLLIN | select.POLLPRI | select.POLLERR)
self._realauthfds = list(map(lambda x: x.fileno(), self.authfds))
self._realacctfds = list(map(lambda x: x.fileno(), self.acctfds))
if self.auth_enabled:
self._realauthfds = list(map(lambda x: x.fileno(), self.authfds))
if self.acct_enabled:
self._realacctfds = list(map(lambda x: x.fileno(), self.acctfds))
if self.coa_enabled:
self._realcoafds = list(map(lambda x: x.fileno(), self.coafds))

def CreateReplyPacket(self, pkt, **attributes):
"""Create a reply packet.
Expand Down Expand Up @@ -221,9 +279,12 @@ def _ProcessInput(self, fd):
if fd.fileno() in self._realauthfds:
pkt = self._GrabPacket(lambda data, s=self: s.CreateAuthPacket(packet=data), fd)
self._HandleAuthPacket(pkt)
else:
elif fd.fileno() in self._realacctfds:
pkt = self._GrabPacket(lambda data, s=self: s.CreateAcctPacket(packet=data), fd)
self._HandleAcctPacket(pkt)
else:
pkt = self._GrabPacket(lambda data, s=self: s.CreateCoAPacket(packet=data), fd)
self._HandleCoaPacket(pkt)

def Run(self):
"""Main loop.
Expand Down

0 comments on commit db780ca

Please sign in to comment.