Example #1
0
def default_holdtime_expiry(clnt):
    """Handle hold time expiry the easy if lame way: Just print a message.
    The "correct" thing to do would be to end the connection at this
    point.  But for the present program, just printing a message and
    doing nothing else seems reasonable."""

    bmisc.stamprint("Hold time expired.")
Example #2
0
 def recv(self):
     "Return a received BGPMessage, or None if there is none"
     if not self.ista:
         # already know there isn't one, don't waste time checking
         if dbg.sokw:
             bmisc.stamprint("SocketWrap.recv(): None")
         return (None)
     if len(self.ipnd) < 19:
         # there isn't a full header
         if dbg.sokw:
             bmisc.stamprint("SocketWrap.recv(): not a full header yet")
         self.ista = False
         return (None)
     # read the message length field of the header
     ml = (self.ipnd[16] << 8) + self.ipnd[17]
     if len(self.ipnd) < ml:
         # there isn't a full message
         if dbg.sokw:
             bmisc.stamprint("SocketWrap.recv(): not a full message yet")
         self.ista = False
         return (None)
     # consume, parse, and return the message
     mr = self.ipnd[:ml]
     self.ipnd = self.ipnd[ml:]
     if dbg.sokw:
         bmisc.stamprint("SocketWrap.recv(): message, " + repr(ml) +
                         " bytes")
     msg = brepr.BGPMessage.parse(self.env, ParseCtx(mr))
     if not self.quiet:
         bmisc.stamprint("Recv: " + str(msg))
     return (msg)
Example #3
0
    def tcp_hex_handler(wrpsok, rw, data):
        if len(data) == 0: return  # nothing to do

        if rw == "r": (posa, rws) = (tcp_hex_ipos, "tcp-rcv")
        else: (posa, rws) = (tcp_hex_opos, "tcp-snd")

        bmisc.stamprint(rws + ", " + str(len(data)) + " bytes:")

        # byte values
        vs = list(map("{:02x}".format, data))

        # padding for alignment with posa[0]
        vs = ["  "] * (posa[0] & 15) + vs

        # display as lines, 16 bytes per line, with an address prefixed to it
        i = 0
        for i in range(0, len(vs), 16):
            print("{}.{:010x}: {}".format(rws, ((posa[0] & ~15) + i),
                                          " ".join(vs[i:(i + 16)])),
                  file=sys.stderr)
        posa[0] += len(data)
Example #4
0
    def able_recv(self):
        """Called when select() indicates this socket can receive something.
        Returns True normally, False if socket closed."""
        if dbg.sokw:
            bmisc.stamprint("SocketWrap.able_recv() called")
        if self.ibroke:
            bmisc.stamprint(
                "SocketWrap.able_recv() doing nothing: conn broken")
            return
        get = 512
        try:
            got = self.sok.recv(get)
        except BrokenPipeError:
            got = bytes()
        except ConnectionResetError:
            got = bytes()

        if len(got):
            self.ipnd += got  # we got something: buffer it
            self.ista = True  # and it *might* be a message
            if self.env.data_cb is not None:
                self.env.data_cb(self, "r", got)
        else:
            # Connection has been closed
            self.ibroke = True
            if dbg.sokw:
                bmisc.stamprint("connection closure detected on recv")
            return (False)
        return (True)
Example #5
0
    def accept_connection(self):
        """Accept a connection on this client's socket, moving it out of
        listen_mode into normal operation."""

        # sanity check
        if not self.listen_mode or self.wrpsok is not None:
            raise Exception("internal error, accepting connection" +
                            " twice or something")

        # get a connection
        sok, remote = self.sok.accept()

        # close and replace the socket since we won't be accepting
        # any more connections on it
        self.sok.close()
        self.sok = sok
        self.wrpsok = boper.SocketWrap(sok, self.env)
        self.wrpsok.set_quiet(self.quiet)
        self.listen_mode = False

        # and announce what's happened
        bmisc.stamprint("Accepted connection from " + repr(remote))
Example #6
0
 def send(self, msg):
     "Queue a BGPMessage for sending"
     if self.obroke:
         bmisc.stamprint("SocketWrap.send(): disabled because connection" +
                         " was closed.")
     self.opnd += msg.raw
     if not self.quiet:
         bmisc.stamprint("Send: " + str(msg))
     if dbg.sokw:
         bmisc.stamprint("SocketWrap.send(): " + repr(len(msg.raw)) +
                         " bytes added to queue, => " +
                         repr(len(self.opnd)))
Example #7
0
 def able_send(self):
     "Called when select() indicates this socket can send something"
     if dbg.sokw:
         bmisc.stamprint("SocketWrap.able_send() called")
     if self.obroke:
         bmisc.stamprint(
             "SocketWrap.able_send() doing nothing: conn broken")
         return
     try:
         sent = self.sok.send(self.opnd)
     except BrokenPipeError:
         sent = 0
     except ConnectionResetError:
         sent = 0
     if sent > 0:
         # we sent something, remove it from the output buffer
         if self.env.data_cb is not None:
             self.env.data_cb(self, "w", self.opnd[:sent])
         self.opnd = self.opnd[sent:]
     else:
         self.obroke = True
         if dbg.sokw:
             bmisc.stamprint("connection closure detected on send")
Example #8
0
    def __init__(self,
                 sok,
                 local_as,
                 router_id,
                 outfile=sys.stdout,
                 errfile=sys.stderr,
                 holdtime_sec=60,
                 holdtime_expiry=default_holdtime_expiry,
                 as4_us=False,
                 rr_us=False,
                 listen_mode=False,
                 quiet=False):
        """Constructor.  Various parameters:
        Required:
            sok -- TCP socket connected to the peer
            local_as -- our local autonomous system (AS) number
            router_id -- router ID -- 32 bit integer or IPv4 address
                represented as int or 4 bytes
        Optional:
            outfile -- regular output stream, default is stdout
            errfile -- error output stream, default is stderr
            holdtime_sec -- hold time to propose in seconds
            holdtime_expiry -- function (passed this Client object) to
                call when the negotiated hold time has expired
            as4_us -- whether to support 4-octet AS number (RFC 6793);
                whether it's actually implemented depends on the peer
            rr_us -- whether to advertise route refresh capability (RFC 2918);
                the actual functionality is not implemented in bgpy
            listen_mode -- whether we're waiting for a connection (True)
                or are already connected (False); True is normal operation
                and is the usual case
            quiet -- whether to suppress many details of what we're doing
                from the log output
        """

        if type(holdtime_sec) is not int:
            raise TypeError("Hold time must be an integer")
        if holdtime_sec != 0 and holdtime_sec < 3:
            raise ValueError("Hold time must be 0 or >= 3 seconds")
        if holdtime_sec > 65535:
            raise ValueError("Hold time may be no more than 65535 seconds")

        self.env = brepr.BGPEnv()
        self.sok = sok
        self.listen_mode = listen_mode
        self.quiet = quiet
        if self.listen_mode:
            self.wrpsok = None  # not connected, can't wrap it yet
        else:
            self.wrpsok = boper.SocketWrap(sok, self.env)
            self.wrpsok.set_quiet(self.quiet)
        self.local_as = local_as
        if type(router_id) is int:
            if (router_id >> 32):
                raise ValueError("Router id must be 32 bits")
            ba = bytearray()
            bmisc.ba_put_be4(ba, router_id)
            router_id = ba
        router_id = bytes(router_id)
        if len(router_id) != 4:
            raise ValueError("Router id must be 32 bits")
        self.router_id = router_id
        self.outfile = outfile
        self.errfile = errfile
        self.holdtime_sec = holdtime_sec
        self.open_sent = None  # BGP Open message we sent if any
        self.open_recv = None  # BGP Open message we received if any
        self.as4_us = as4_us
        self.rr_us = rr_us

        if self.listen_mode:
            bmisc.stamprint("Listening.")
        else:
            bmisc.stamprint("Connected.")
Example #9
0
if len(sys.argv) < 2:
    usage()

for a in sys.argv[1:-1]:
    try:
        equal_parms.parse(a)
    except Exception as e:
        print(str(e), file=sys.stderr)
        if dbg.estk:
            print_exc(file=sys.stderr)
        usage()

peer_addr = sys.argv[-1]

bmisc.stamprint("Started.")

# figure out addresses

af, connect_addr = bmisc.addr_for_socket(peer_addr, port=brepr.BGP_TCP_PORT)

bind_to = None

if equal_parms["local-addr"] != "" or equal_parms["passive"]:
    bind_to_addr = equal_parms["local-addr"]
    if bind_to_addr == "":
        if af == socket.AF_INET:
            bind_to_addr = "0.0.0.0"
        else:
            bind_to_addr = "::"
    bind_to_port = None