X-Git-Url: http://git.samba.org/?p=samba.git;a=blobdiff_plain;f=prog_guide4.txt;h=0a33284e579a31c8d751b8e930778ff21100fdaf;hp=2f5be5f7915582977ad0bbed19a21c0aad04ea00;hb=2f86e32a993727f61d61f9a254dafff9efdb769f;hpb=729ffbae086309992d7433a296fca64f6800f8fa diff --git a/prog_guide4.txt b/prog_guide4.txt index 2f5be5f7915..0a33284e579 100644 --- a/prog_guide4.txt +++ b/prog_guide4.txt @@ -5,7 +5,9 @@ FROM A FEW PEOPLE. DON'T TAKE THIS AS THE FINAL VERSION YET. Samba4 Programming Guide ------------------------- +======================== + +.. contents:: The internals of Samba4 are quite different from previous versions of Samba, so even if you are an experienced Samba developer please take @@ -144,8 +146,7 @@ data is a bug waiting to happen. Static data is evil as it has the following consequences: - it makes code much less likely to be thread-safe - it makes code much less likely to be recursion-safe -- it leads to subtle side effects when the same code is called from - multiple places +- it leads to subtle side effects when the same code is called from multiple places - doesn't play well with shared libraries or plugins Static data is particularly evil in library code (such as our internal @@ -202,7 +203,7 @@ Interface Structures -------------------- One of the biggest changes in Samba4 is the universal use of interface -structures. Go take a look through include/smb_interfaces.h now to get +structures. Go take a look through libcli/raw/interfaces.h now to get an idea of what I am talking about. In Samba3 many of the core wire structures in the SMB protocol were @@ -266,16 +267,16 @@ parser where to find the following four variables, but they should In Samba3 there were unwritten rules about which variables in a structure a high level caller has to fill in and which ones are filled in by the marshalling code. In Samba4 those rules are gone, because -the redundent artifact variables are gone. The high level caller just +the redundant artifact variables are gone. The high level caller just sets up the real variables and the marshalling code worries about generating the right offsets. The same rule applies to strings. In many places in the SMB and MSRPC protocols complex strings are used on the wire, with complex rules about padding, format, alighment, termination etc. None of that -information is useful to a high level calling routine or to a backend -- its all just so much wire fluff. So, in Samba4 these strings are -just "char *" and are always in our internal multi-byte format (which +information is useful to a high level calling routine or to a backend - its +all just so much wire fluff. So, in Samba4 these strings are +just "char \*" and are always in our internal multi-byte format (which is usually UTF8). It is up to the parse functions to worry about translating the format and getting the padding right. @@ -285,10 +286,10 @@ read the comment in smb_interfaces.h about that now. So, here is another rule to code by. When writing an interface structure think carefully about what variables in the structure can be -left out as they are redundent. If some length is effectively defined +left out as they are redundant. If some length is effectively defined twice on the wire then only put it once in the packet. If a length can be inferred from a null termination then do that and leave the length -out of the structure completely. Don't put redundent stuff in +out of the structure completely. Don't put redundant stuff in structures! @@ -320,11 +321,11 @@ is always called smb_raw_XXXX_send(), constructs and sends a SMB request and returns a "struct cli_request" which acts as a handle for the request. The caller is then free to do lots of other calls if it wants to, then when it is ready it can call the smb_raw_XXX_recv() -function to receive the reply. +function to receive the reply. If all you want is a synchronous call then call the 3rd interface, the one called smb_raw_XXXX(). That just calls the first two in order, and -blocks waiting for the reply. +blocks waiting for the reply. But what if you want to be called when the reply comes in? Yes, thats possible. You can do things like this:: @@ -396,27 +397,13 @@ function, so smbd has a _send() function and the parse function for each SMB. As an example go and have a look at reply_getatr_send() and -reply_getatr() in smb_server/reply.c. Read them? Good. +reply_getatr() in smb_server/smb/reply.c. Read them? Good. Notice that reply_getatr() sets up the req->async structure to contain the send function. Thats how the backend gets to do an async reply, it calls this function when it is ready. Also notice that reply_getatr() only does the parsing of the request, and does not do the reply -generation. That is done by the _send() function. - -The only missing piece in the Samba4 right now that prevents it being -fully async is that it currently does the low level socket calls (read -and write on sockets) in a blocking fashion. It does use select() to -make it somewhat async, but if a client were to send a partial packet -then delay before sending the rest then smbd would be stuck waiting -for the second half of the packet. - -To fix this I plan on making the socket calls async as well, which -luckily will not involve any API changes in the core of smbd or the -library. It just involves a little bit of extra code in clitransport.c -and smbd/request.c. As a side effect I hope that this will also reduce -the average number of system calls required to answer a request, so we -may see a performance improvement. +generation. That is done by the _send() function. NTVFS @@ -444,7 +431,7 @@ client. Lets have a look at one of those request structures. Go and read the definition of "union smb_write" and "enum write_level" in -include/smb_interfaces.h. (no, don't just skip reading it, really go +libcli/raw/interfaces.h. (no, don't just skip reading it, really go and read it. Yes, that means you!). Notice the union? That's how Samba4 allows a single NTVFS backend @@ -454,21 +441,20 @@ union:: /* SMBwriteX interface */ struct { - enum write_level level; - + enum smb_write_level level; struct { - uint16 fnum; - SMB_BIG_UINT offset; - uint16 wmode; - uint16 remaining; - uint32 count; - const char *data; + union smb_handle file; + uint64_t offset; + uint16_t wmode; + uint16_t remaining; + uint32_t count; + const uint8_t *data; } in; struct { - uint32 nwritten; - uint16 remaining; + uint32_t nwritten; + uint16_t remaining; } out; - } writex; + } writex, generic; see the "in" and "out" sections? The "in" section is for parameters that the SMB client sends on the wire as part of the request. The smbd @@ -491,7 +477,7 @@ the same variable. Notice also that some levels (such as splwrite) don't have an "out" section. This happens because there is no return value apart from a -status code from those SMB calls. +status code from those SMB calls. So what about status codes? The status code is returned directly by the backend NTVFS interface when the call is performed @@ -516,14 +502,14 @@ the process model that Samba3 supported is the "right" one for most users, but there are situations where this model wasn't ideal. In Samba4 you can choose the smbd process model on the smbd command -line. +line. DCERPC binding strings ---------------------- When connecting to a dcerpc service you need to specify a binding -string. +string. The format is: @@ -531,8 +517,8 @@ The format is: where TRANSPORT is either ncacn_np for SMB or ncacn_ip_tcp for RPC/TCP -"host" is an IP or hostname or netbios name. If the binding string -identifies the server side of an endpoint, "host" may be an empty +"host" is an IP or hostname or netbios name. If the binding string +identifies the server side of an endpoint, "host" may be an empty string. "flags" can include a SMB pipe name if using the ncacn_np transport or @@ -577,16 +563,20 @@ IDEA: Maybe extend UNC names like this? DCERPC Handles -------------- -The various handles that are used in the RPC servers should be created and +The various handles that are used in the RPC servers should be created and fetch using the dcesrv_handle_* functions. -Use dcesrv_handle_new(struct dcesrv_connection *, uint8 handle_type) to obtain -a new handle of the specified type. Handle types are unique within each +Use dcesrv_handle_new(struct dcesrv_connection \*, uint8 handle_type) to obtain +a new handle of the specified type. Handle types are unique within each pipe. -The handle can later be fetched again using -struct dcesrv_handle *dcesrv_handle_fetch(struct dcesrv_connection *dce_conn, struct policy_handle *p, uint8 handle_type) -and destroyed by dcesrv_handle_destroy(struct dcesrv_handle *). +The handle can later be fetched again using:: + + struct dcesrv_handle *dcesrv_handle_fetch(struct dcesrv_connection *dce_conn, struct policy_handle *p, uint8 handle_type) + +and destroyed by:: + + dcesrv_handle_destroy(struct dcesrv_handle *). User data should be stored in the 'data' member of the dcesrv_handle struct. @@ -765,12 +755,10 @@ BUGS: no 137 resolution not possible should not fallback to anon when pass supplied should check pass-thu cap bit, and skip lots of tests - possibly allow the test suite to say "allow oversized replies" for - trans2 and other calls + possibly allow the test suite to say "allow oversized replies" for trans2 and other calls handle servers that don't have the setattre call in torture add max file coponent length test and max path len test - check for alloc failure in all core reply.c and trans2.c code where - allocation size depends on client parameter + check for alloc failure in all core reply.c and trans2.c code where allocation size depends on client parameter case-insenstive idea: all filenames on disk lowercase