Clean up top dir.
[radsecproxy.git] / develdoc.txt
diff --git a/develdoc.txt b/develdoc.txt
deleted file mode 100644 (file)
index 05ee56e..0000000
+++ /dev/null
@@ -1,279 +0,0 @@
-radsecproxy documentation for developers
-
-1. Overall design
-
-At startup client and server configurations are read. Two lists
-are created, called clconfs and srvconfs. Both contain clsrvconf
-structs.
-
-For each server config, a client writer thread is created. This
-takes care of sending requests to a server.
-
-Next for each known transport type which has a configured client,
-we create listeners. Typically there is a default server port
-that will be listened on, but multiple ports might be configured.
-For each port there will normally be 1-2 sockets (IPv4 and/or IPv6).
-For each socket a thread is created with the listener() defined for
-the transport.
-
-This is all that happens in the main thread. The threads created
-above need to take care of the rest.
-
-Client writers are generally responsible for sending messages to
-clients, and if necessary creating and maintaining connections to
-the client. Client writers create threads for handling replies from
-servers. If connections are used, one thread is created for reading
-from each connection. clientwr() will use connecter() and
-clientconnreader() definitions for the transport.
-
-The listeners may receive RADIUS messages directly, which is the
-case for UDP which is not connection based. Or they may receive
-connections and create a new thread for handling each incoming
-connection, where that thread will receive RADIUS messages.
-The function receiving RADIUS client requests is generally called
-xxxserverrd, where xxx is the transport name. The server reader
-is responsible for creating a server writer thread that takes care
-of sending RADIUS replies to a client.
-
-2. RADIUS message processing
-
-In 1 we described the threads used and the high level operations.
-We will now describe how RADIUS messages are processed and flow
-through the system.
-
-An incoming RADIUS request from a client is handled by a server
-reader. The server reader calls newrequest() to obtain a request
-struct. It sets rq->buf to point to the received message, rq->from
-to point to the client struct for the client, and might for some
-transports specify additional data. E.g. for UDP, the source port
-and socket it was received on. The reader must make sure buf is
-at least as large as the specified RADIUS message length. The
-client reader calls radsrv(rq). When that returns it just waits
-for the next message.
-
-radsrv() is in a way the core part of the proxy. It takes care
-of validation, processing and routing of incoming requests.
-It first creates a radmsg struct calling buf2radmsg(). This also
-takes care of basic validation (e.g. that lengths add up) and
-checking message authenticators. Unless it receives a valid
-Access Request, Accounting Request or Status Server, it will
-drop the request and return.
-
-It next calls addclientrq() which adds this request to a request
-queue for rq->from. Before adding it to the queue, it checks if
-it is a duplicate of something already in the queue. If a
-duplicate, radsrv() drops the request and returns.
-
-Next radsrv() checks if it received a Status Server message. In
-that case it responds with Access Accept and returns.
-
-Next it applies any rewritein rules and also checks TTL attribute.
-If TTL expired, it will drop request and return.
-
-Next it looks for a User-Name attribute. If not present it will
-will drop the request. However, if it is an accounting request
-it will first send an accounting response.
-
-Next it calls findserver() to pick a server for sending the
-message to. For this it will use the user-name attribute and the
-realm definitions. It also takes into account which servers are
-alive.
-
-If no server is found it will drop the message. However, in
-certain cases it may send a reject or accounting response message.
-
-Next it reencrypts any attributes that are encrypted based on
-the secrets of clients/servers. And after that, decrements TTL if
-present, and applies any rewriteout rules.
-
-Finally radsrv() calls sendrq(rq) to pass the request to the
-chosen server.
-
-sendrq() checks the request queue for a server. The request queue
-is an array holding 256 entries, one for each possible message ID.
-Normally it will start looking for a free slot at the ID after the
-last entry inserted in the queue (0 follows 255). However in a
-special case where sendrq() is called to send a status-server message,
-it will always use ID 0. If status-server is enabled, ID 0 is not used
-for other requests. If there are no free slots, the message is
-discarded.
-
-When finding a free slot, it does, "to->requests[i].rq = rq" and
-signals the writer thread : "pthread_cond_signal(&to->newrq_cond)".
-After that, it returns, and the server reader thread can wait for a
-new client request.
-
-We will now consider the client writer thread that takes care of
-sending this request to a server.
-
-clientwr() continually looks for requests in its request buffer
-and tries to send them to a server. It uses timers so that it can
-sleep waiting for a new request, or sending status server, or
-re-sending an existing request. When a new request comes in, it
-will send it ASAP to the server and set tries to 1. For the
-server there is a retryinterval timer. retryinterval seconds later
-clientwr() will resend or remove the request. It is removed if the
-server's retrycount parameter is exceeded (0 retries if reliable
-transport). Status server messages are never resent.
-
-The handling of the request stops here, unless we get a reply.
-We will now describe how replies are handled.
-
-Each transport has a function called something xxxclientrd() for
-receiving replies from a server. This is run as a separate thread.
-All they do is read a RADIUS message and call replyh(server, buf)
-where server points to the server struct for the server, and buf
-is a buffer large enough to contain the entire RADIUS message. It
-will not read another message until replyh() returns.
-
-We will now consider replyh(). It will first check if there is an
-outstanding request matching the id of the reply. This is done by
-checking the request queue of the server.
-
-If it maches a request, it will validate and authenticate the
-reply by calling buf2radmsg(). If this fails or the message type
-is not one of Access Accept, Access Reject, Access Challenge or
-Accounting Response, the reply is ignored.
-
-If the request was a status-server message, it simply removes
-the request and returns.
-
-Next it will apply any rewritein rules and check TTL attribute if
-present. If TTL is exceeded, the reply is ignored.
-
-Next it reencrypts some attributes with the secret of the client
-the original request came from, and which the reply will be sent
-back to. It also applies any rewriteout rules.
-
-Finally to pass the reply back to the client, it does
-"rqout->rq->msg = msg" to store the reply message in the request,
-and calls sendreply() with rqout->rq as parameter. When
-sendreply() returns, we free the request from the server's
-request queue. This also means that the ID can be used for a new
-request.
-
-Now about sendreply(). All it does is basically to assemble the
-reply message, take care of authenticators and set rq->replybuf
-to point to the result. After that it adds a pointer to rq to
-the clients reply queue and signals the server writer who is
-responsible for sending replies to the client.
-
-The server writer is a separate thread created by the server reader,
-typically called something like xxxserverwr. All it does is to send
-whatever it finds in its replyq to the client and remove it. When
-the queue is empty it waits for a signal from a sendreply().
-
-The above shows the complete flow. It might be worth also looking a
-bit more at the state created for each request though.
-
-As mentioned above, each request received from a client is stored in
-request queue for the client. The request is stored in a request
-struct which looks like this:
-
-struct request {
-    uint8_t *buf, *replybuf;
-    struct radmsg *msg;
-    ...
-};
-
-This request will remain in the queue until a new request is
-received with the same id and which is not a duplicate. The
-new one then replaces the previous.
-
-Initially for a new request, only buf is used (of the above specified
-fields). Next the message is parsed and validated, and if ok, it is
-stored in msg. buf with the request is freed.
-
-In sendrq() a request that is to be sent to a server, is again
-reassembled from rq->msg into rq->buf.
-
-When a reply is received, it will again be parsed and validated, and
-if ok, it will free the old rq->msg, and store the new instead.
-
-Finally, in sendreply() rq->replybuf is created from rq->msg, and
-rq->msg is freed. rq->replybuf is kept so that if a duplicate request
-is received later, we can just return rq->replybuf.
-
-rq->buf is removed by freerqoutdata(), because then we will not try
-to send the request in rq->buf any more.
-
-Request structs should perhaps be freed when they "expire", rather
-than wait until a new request with the same ID comes along.
-
-x. Transports
-
-struct protodefs protodefs[] contains definitions of the different
-transport protocols. We will here describe the different parameters.
-
-struct protodefs {
-    char *name;
-This should be a textual name for the transport, e.g. "udp". This is
-used in client/server configurations and for debug/log messages.
-    
-    char *secretdefault;
-Some transports like TLS that provides strong encryption, may have a
-default RADIUS secret, since the RADIUS encryption is not needed.
-    
-    uint8_t socktype;
-Typically set to SOCK_DGRAM or SOCK_STREAM. This is used when a
-socket for the transport is created.
-    
-    char *portdefault;
-The default server port for the transport, e.g. 1812.
-    
-    uint8_t retrycountdefault;
-How many time a client request should be resent. For a reliable
-transport like TCP/TLS, this should be 0.
-    
-    uint8_t retrycountmax;
-The maximum allowed configurable value for retrycount. For reliable
-transport it should probably be 0.
-    
-    uint8_t retryintervaldefault;
-This is the default for how many seconds there should be between each
-retry. For a reliable transport with 0 retries, this controls how
-long it should wait for a reply to the client request.
-    
-    uint8_t retryintervalmax;
-This is the maximum allowed retryinterval
-    
-    uint8_t duplicateintervaldefault;
-This is the time period two requests with the same UDP source port
-and request authenticator are considered duplicates. If a reply has
-been sent to the first request, then that is resent. If no reply
-has been sent, the second request is ignored.
-    
-    void *(*listener)(void*);
-Each transport must define a listener function for the sockets
-created by the transport. The socket is created by radsecproxy
-core. If successful, the listener is called.
-    
-    int (*connecter)(struct server *, struct timeval *, int, char *);
-When creating a new server, a clientwr() thread is created for sending
-requests to the server. If a connecter() is defined for the transport,
-clientwr() will call connecter() and exit if connecter() returns 0.
-
-    void *(*clientconnreader)(void*);
-If a connecter() is defined, then when that successfully returns,
-a separate thread is created for reading from the connection. This
-thread is responsible for handling replies from a server.
-
-    int (*clientradput)(struct server *, unsigned char *);
-Used by clientwr() for sending a RADIUS message.
-
-    void (*addclient)(struct client *);
-Need only be defined if need to override default client creation.
-Used by UDP to have a common reply queue, rather than one per client.
-
-    void (*addserverextra)(struct clsrvconf *);
-Need only be defined if something needs to be done in addition to
-the default server creation.
-    
-    uint8_t freesrcprotores;
-Whether should free the resolver state for source ports and
-addresses after initial startup.
-
-    void (*initextra)();
-Can be defined it extra initialisation is needed for the transport.
-
-};