Printing arguments to a kernel function in dtrace - network-programming

I need to debug my Solaris kernel module particularly extract the data in a structure passed by reference to my kernel function.
msg_recv(sk_buff *skbp, uint_t link, uchar_t* src)
{
pkt_hdr_t *pkt;
pkt = (pkt_hdr_t *)skbp->data;
port = pkt->port;
}
I have written a systemtap script in linux to access the argument and extract data.
How can I do this using DTRACE for solaris modules.
I tried looking into the system and trying few commands, but thats all i know about dtrace:
[root#vcssx247-ldm7 ~]#dtrace -l | grep msg_recv
7090 fbt mymod msg_recv1 entry
7091 fbt mymod msg_recv1 return
7548 fbt mymod msg_recv entry
7549 fbt mymod msg_recv return

DTrace is similar conceptually to SystemTap (actually, vice versa as SystemTap came later):
Like SystemTap, it can attach probes to function, but it requires different syntax:
kernel.function("xxx") -> fbt:genunix:xxx:return
module("mod").function("xxx") -> fbt:mod:xxx:entry
module("mod").function("xxx").return -> fbt:mod:xxx:return
Accessing arguments is quite different as DTrace doesn't support DWARF for argument names (it has arg0 .. arg9 variables which contains uintptr_t values of arguments):
#cast($skpb, "struct sk_buff", "mod") -> ((struct sk_buff*) arg0)
Accessing in-kernel data, is similar, but printing functions are different:
print($skpb->sk_field) -> trace(args[0]->sk_field)
print("%32m", $src) -> tracemem(arg2, 32)
I've added links to my open book about DTrace/SystemTap where you can find more info

Related

Different behaviour of ETS with and without a shell

First a disclaimer I am learning erlang. Not an expert here at all.
While making some examples using ETS I came across something I am not understanding (even after searching).
I have a process where I create a public ETS with
TableID = ets:new(tablename, [public])}
I then pass TableID to other processes. When I do this running the modules form the shell, all is ok. When I run exactly the same modules with erl -noshell -s ... or even without the -noshell option, it fails.
I keep getting error:badarg as if the tabled does not exist. The ID is properly passes, but the table is actually behaving as private!
Is there a difference between running modules interactively from the shell or without?
Thanks
I am adding an example of the code I am using to try and debug the issue. As it is a piece of a larger software (and it is basically stripped to the bone to find the issue), it might be difficult to understand.
-record(loop_state, {
commands
}).
start() ->
LoopState = #loop_state{commands = ets:new(commands, [public])},
tcpserver_otp_backend:start(?MODULE, 7000, {?MODULE, loop}, LoopState).
loop(Socket, LoopState = #loop_state{commands = Commands}) ->
case gen_tcp:recv(Socket, 0) of
{ok, Data} ->
% the call below fails, no error generated, AND only in non interactive shell
A = newCommand(Commands, Data),
gen_tcp:send(Socket, A),
loop(Socket, LoopState);
{error, closed} ->
ok
end.
newCommand(CommandTableId, Command) ->
case ets:lookup(CommandTableId,Command) of
[] ->
_A = ets:insert(CommandTableId, {Command, 1}),
<<1, "new", "1">>; % used for testing
_ ->
<<1, "old", "1">> % used for testing
end.
When I remove the "offending command" ets:lookup, all works again as int he interactive shell.
The problem seems to be that you create the ets table in your start() function. An ets table has an owner (by default the creating process), and when the owner dies, the table gets deleted. When you run the start/0 function from the command line by passing -s to erl, that owner process will be some internal process in the Erlang kernel that is part of handling the startup sequence. Regardless of whether you pass -noshell or not, that process is probably transient and will die before the lookup function gets time to execute, so the table no longer exists when the lookup finally happens.
The proper place to create the ets table would be in the init() callback function of the gen_server that you start up. If it's supposed to be a public est table accessed by several processes, then you might want to create a separate server process whose task it is to own the table.

Validate URL in Informix 4GL program

In my Informix 4GL program, I have an input field where the user can insert a URL and the feed is later being sent over to the web via a script.
How can I validate the URL at the time of input, to ensure that it's a live link? Can I make a call and see if I get back any errors?
I4GL checking the URL
There is no built-in function to do that (URLs didn't exist when I4GL was invented, amongst other things).
If you can devise a C method to do that, you can arrange to call that method through the C interface. You'll write the method in native C, and then write an I4GL-callable C interface function using the normal rules. When you build the program with I4GL c-code, you'll link the extra C functions too. If you build the program with I4GL-RDS (p-code), you'll need to build a custom runner with the extra function(s) exposed. All of this is standard technique for I4GL.
In general terms, the C interface code you'll need will look vaguely like this:
#include <fglsys.h>
// Standard interface for I4GL-callable C functions
extern int i4gl_validate_url(int nargs);
// Using obsolescent interface functions
int i4gl_validate_url(int nargs)
{
if (nargs != 1)
fgl_fatal(__FILE__, __LINE__, -1318);
char url[4096];
popstring(url, sizeof(url));
int r = validate_url(url); // Your C function
retint(r);
return 1;
}
You can and should check the manuals but that code, using the 'old style' function names, should compile correctly. The code can be called in I4GL like this:
DEFINE url CHAR(256)
DEFINE rc INTEGER
LET url = "http://www.google.com/"
LET rc = i4gl_validate_url(url)
IF rc != 0 THEN
ERROR "Invalid URL"
ELSE
MESSAGE "URL is OK"
END IF
Or along those general lines. Exactly what values you return depends on your decisions about how to return a status from validate_url(). If need so be, you can return multiple values from the interface function (e.g. error number and text of error message). Etc. This is about the simplest possible design for calling some C code to validate a URL from within an I4GL program.
Modern C interface functions
The function names in the interface library were all changed in the mid-00's, though the old names still exist as macros. The old names were:
popstring(char *buffer, int buflen)
retint(int retval)
fgl_fatal(const char *file, int line, int errnum)
You can find the revised documentation at IBM Informix 4GL v7.50.xC3: Publication library in PDF in the 4GL Reference Manual, and you need Appendix C "Using C with IBM Informix 4GL".
The new names start ibm_lib4gl_:
ibm_libi4gl_popMInt()
ibm_libi4gl_popString()
As to the error reporting function, there is one — it exists — but I don't have access to documentation for it any more. It'll be in the fglsys.h header. It takes an error number as one argument; there's the file name and a line number as the other arguments. And it will, presumably, be ibm_lib4gl_… and there'll be probably be Fatal or perhaps fatal (or maybe Err or err) in the rest of the name.
I4GL running a script that checks the URL
Wouldn't it be easier to write a shell script to get the status code? That might work if I can return the status code or any existing results back to the program into a variable? Can I do that?
Quite possibly. If you want the contents of the URL as a string, though, you'll might end up wanting to call C. It is certainly worth thinking about whether calling a shell script from within I4GL is doable. If so, it will be a lot simpler (RUN "script", IIRC, where the literal string would probably be replaced by a built-up string containing the command and the URL). I believe there are file I/O functions in I4GL now, too, so if you can get the script to write a file (trivial), you can read the data from the file without needing custom C. For a long time, you needed custom C to do that.
I just need to validate the URL before storing it into the database. I was thinking about:
#!/bin/bash
read -p "URL to check: " url
if curl --output /dev/null --silent --head --fail "$url"; then
printf '%s\n' "$url exist"
else
printf '%s\n' "$url does not exist"
fi
but I just need the output instead of /dev/null to be into a variable. I believe the only option is to dump the output into a temp file and read from there.
Instead of having I4GL run the code to validate the URL, have I4GL run a script to validate the URL. Use the exit status of the script and dump the output of curl into /dev/null.
FUNCTION check_url(url)
DEFINE url VARCHAR(255)
DEFINE command_line VARCHAR(255)
DEFINE exit_status INTEGER
LET command_line = "check_url ", url
RUN command_line RETURNING exit_status
RETURN exit_status
END FUNCTION {check_url}
Your calling code can analyze exit_status to see whether it worked. A value of 0 indicates success; non-zero indicates a problem of some sort, which can be deemed 'URL does not work'.
Make sure the check_url script (a) exits with status zero on success and non-zero on any sort of failure, and (b) doesn't write anything to standard output (or standard error) by default. The writing to standard error or output will screw up screen layouts, etc, and you do not want that. (You can obviously have options to the script that enable standard output, or you can invoke the script with options to suppress standard output and standard error, or redirect the outputs to /dev/null; however, when used by the I4GL program, it should be silent.)
Your 'script' (check_url) could be as simple as:
#!/bin/bash
exec curl --output /dev/null --silent --head --fail "${1:-http://www.example.com/"
This passes the first argument to curl, or the non-existent example.com URL if no argument is given, and replaces itself with curl, which generates a zero/non-zero exit status as required. You might add 2>/dev/null to the end of the command line to ensure that error messages are not seen. (Note that it will be hell debugging this if anything goes wrong; make sure you've got provision for debugging.)
The exec is a minor optimization; you could omit it with almost no difference in result. (I could devise a scheme that would probably spot the difference; it involves signalling the curl process, though — kill -9 9999 or similar, where the 9999 is the PID of the curl process — and isn't of practical significance.)
Given that the script is just one line of code that invokes another program, it would be possible to embed all that in the I4GL program. However, having an external shell script (or Perl script, or …) has merits of flexibility; you can edit it to log attempts, for example, without changing the I4GL code at all. One more file to distribute, but better flexibility — keep a separate script, even though it could all be embedded in the I4GL.
As Jonathan said "URLs didn't exist when I4GL was invented, amongst other things". What you will find is that the products that have grown to superceed Informix-4gl such as FourJs Genero will cater for new technologies and other things invented after I4GL.
Using FourJs Genero, the code below will do what you are after using the Informix 4gl syntax you are familiar with
IMPORT com
MAIN
-- Should succeed and display 1
DISPLAY validate_url("http://www.google.com")
DISPLAY validate_url("http://www.4js.com/online_documentation/fjs-fgl-manual-html/index.html#c_fgl_nf.html") -- link to some of the features added to I4GL by Genero
-- Should fail and display 0
DISPLAY validate_url("http://www.google.com/testing")
DISPLAY validate_url("http://www.google2.com")
END MAIN
FUNCTION validate_url(url)
DEFINE url STRING
DEFINE req com.HttpRequest
DEFINE resp com.HttpResponse
-- Returns TRUE if http request to a URL returns 200
TRY
LET req = com.HttpRequest.create(url)
CALL req.doRequest()
LET resp = req.getResponse()
IF resp.getStatusCode() = 200 THEN
RETURN TRUE
END IF
-- May want to handle other HTTP status codes
CATCH
-- May want to capture case if not connected to internet etc
END TRY
RETURN FALSE
END FUNCTION

haskell - Parsing command-line and REPL commands and options

I'm writing a program that has both a command-line interface and an interactive mode. In CLI mode it executes one command, prints results and exits. In interactive mode it repeatedly reads commands using GNU readline, executes them and prints results (in spirit of a REPL).
The syntax for commands and their parameters is almost the same regardless of whether they come from command-line or frmo stdin. I would like to maximize code-reuse by using a single framework for parsing both command-line and interactive mode inputs.
My proposed syntax is (square brackets denote optional parts, braces repetition) as follows:
From shell:
program-name {[GLOBAL OPTION] ...} <command> [{<command arg>|<GLOBAL OPTION>|<LOCAL OPTION> ...}]
In interactive mode:
<command> [{<command arg>|<GLOBAL OPTION>|<LOCAL OPTION> ...}]
Local options are only valid for one particular command (different commands may assign a different meaning to one option).
My problem is that there are some differences between the CL and interactive interfaces:
Some global options are only valid from command line (like --help, --version or --config-file). There is obviously also the 'quit'-command which is very important in interactive mode, but using it from CL makes no sense.
To solve this I've searched web and hackage for command-line parsing libraries. The most interesting ones I've found are cmdlib and optparse-applicative. However, I'm quite new to Haskell and even though I can create a working program by copying and modifying example code from library docs, I haven't quite understood the mechanics of these libraries and therefore have not been able to solve my problem.
I have these questions in mind:
How to make a base parser for commands and options that are common to CL and REPL interfaces and then be able to extend the base parser with new commands and options?
How to prevent these libraries from exiting my program upon incorrect input or when '--help' is used?
I plan to add complete i18n support to my program. Therefore I would like to prevent my chosen library from printing any messages, because all messages need to be translated. How to achieve this?
So I wish you could give me some hints on where to go from here. Does cmdlib or optparse-applicative (or some other library) support what I'm looking for? Or should I revert to a hand-crafted parser?
I think you could use my library http://hackage.haskell.org/package/options to do this. The subcommands feature exactly matches the command flag parsing behavior you're looking for.
It'd be a little tricky to share subcommands between two disjoint sets of options, but a helper typeclass should be able to do it. Rough sample code:
-- A type for options shared between CLI and interactive modes.
data CommonOptions = CommonOptions
{ optSomeOption :: Bool
}
instance Options CommonOptions where ...
-- A type for options only available in CLI mode (such as --version or --config-file)
data CliOptions = CliOptions
{ common :: CommonOptions
, version :: Bool
, configFile :: String
}
instance Options CliOptions where ...
-- if a command takes only global options, it can use this subcommand option type.
data NoOptions = NoOptions
instance Options NoOptions where
defineOptions = pure NoOptions
-- typeclass to let commands available in both modes access common options
class HasCommonOptions a where
getCommonOptions :: a -> CommonOptions
instance HasCommonOptions CommonOptions where
getCommonOptions = id
instance HasCommonOptions CliOptions where
getCommonOptions = common
commonCommands :: HasCommonOptions a => [Subcommand a (IO ())]
commonCommands = [... {- your commands here -} ...]
cliCommands :: HasCommonOptions a => [Subcommand a (IO ())]
cliCommands = commonCommands ++ [cmdRepl]
interactiveCommands :: HasCommonOptions a => [Subcommand a (IO ())]
interactiveCommands = commonCommands ++ [cmdQuit]
cmdRepl :: HasCommonOptions a => Subcommand a (IO ())
cmdRepl = subcommand "repl" $ \opts NoOptions -> do
{- run your interactive REPL here -}
cmdQuit :: Subcommand a (IO ())
cmdQuit = subcommand "quit" (\_ NoOptions -> exitSuccess)
I suspect the helper functions like runSubcommand wouldn't be specialized enough, so you'll want to invoke the parser with parseSubcommand once you've split up the input string from the REPL prompt. The docs have examples of how to inspect the parsed options, including checking whether the user requested help.
The options parser itself won't print any output, but it may be difficult to internationalize error messages generated by the default type parsers. Please let me know if there's any changes to the library that would help.

How to pass extra arguments to RabbitMQ connection in Erlang client

I have written some extension modules for eJabberd most of which pass pieces of information to RabbitMQ for various reasons. All has been fine until we brought the server up in staging where we have a Rabbit cluster rather than a single box.
In order to utilize the cluster you need to pass "x-ha-policy" parameter to Rabbit with either the "all" or "nodes" value. This works fine for the Java and Python Producers and Consumers, but the eJabberd (using the Erlang AMQP client of course) has me a bit stumped. The x-ha-policy parameter needs to be passed into the "client_properties" parameter which is just the "catchall" for extra parameters.
In Python with pika I can do:
client_params = {"x-ha-policy": "all"}
queue.declare(host, vhost, username, password, arguments=client_params)
and that works. However the doc for the Erlang client says the arguments should be passed in as a list per:
[{binary(), atom(), binary()}]
If it were just [{binary(), binary()}] I could see the relationship with key/value but not sure what the atom would be there.
Just to be clear, I am a novice Erlang programmer so this may be a common construct that I am not familiar with, so no answer would be too obvious.
I found this in amqp_network_connection.erl, which looks like a wrapper to set some default values:
client_properties(UserProperties) ->
{ok, Vsn} = application:get_key(amqp_client, vsn),
Default = [{<<"product">>, longstr, <<"RabbitMQ">>},
{<<"version">>, longstr, list_to_binary(Vsn)},
{<<"platform">>, longstr, <<"Erlang">>},
{<<"copyright">>, longstr,
<<"Copyright (c) 2007-2012 VMware, Inc.">>},
{<<"information">>, longstr,
<<"Licensed under the MPL. "
"See http://www.rabbitmq.com/">>},
{<<"capabilities">>, table, ?CLIENT_CAPABILITIES}],
lists:foldl(fun({K, _, _} = Tuple, Acc) ->
lists:keystore(K, 1, Acc, Tuple)
end, Default, UserProperties).
Apparently the atom describes the value type. I don't know the available types, but there's a chance that longstr will work in your case.

What does in ? operator/prefix in Erlang mean?

What does the question mark in ?MODULE (which can be seen in all generated code by Mochiweb make command) mean?
-export([start/1, stop/0, loop/2]).
start(Options) ->
{DocRoot, Options1} = get_option(docroot, Options),
Loop = fun (Req) ->
?MODULE:loop(Req, DocRoot)
end,
mochiweb_http:start([{name, ?MODULE}, {loop, Loop} | Options1]).
stop() ->
mochiweb_http:stop(?MODULE).
loop(Req, DocRoot) ->
...
It denotes a preprocessor macro. ?MODULE is one of the predefined macro constants that expand to current module's name.
Well this is the way we represent MACROS in Erlang. At compile time, these macros are replaced with the actual meanings. They save on re-writing pieces of code or on abstracting out a parameter you may change in future without changing your code (would only require a re-compilation of the source that depends on the MACRO).
Forexample:
-module(square_plus).
-compile(export_all).
-define(SQUARE(X),X * X).
add_to_square(This,Number)-> ?SQUARE(This) + Number.
Is the same as:
-module(square_plus).
-compile(export_all).
add_to_square(This,Number)-> (This * This) + Number.
-define(Macro,Replacement). is used by the preprocessor to supports macros to have more readable programs. It can be used to have a conditional compilation. It is recommended that If a macro is used in several modules, it's definition is placed in an include file.
A macro definition example:
-define(TIMEOUT, 200).
For using macro:
?TIMEOUT.
List of predefined macros:
?MODULE: The name of the current module.
?FILE: The file name of the current module.
?LINE: The current line number.
?MACHINE: The machine name.
Source: https://www.dcs.gla.ac.uk/~amirg/tutorial/erlang/

Resources