How can I find mount point of a device in C/C++? - c

I am using libhal to detect device events. I am able to detect a device added or removed but I can not detect device's mount point. The function libhal_volume_get_mount_point(volume) does not work.
I have a callback function to detect device add:
static void handle_device_added(LibHalContext *ctx, const char *udi) {
dbus_bool_t is_storage;
dbus_bool_t is_volume;
is_storage = libhal_device_query_capability(ctx, udi, "storage", NULL);
is_volume = libhal_device_query_capability(ctx, udi, "volume", NULL);
if (is_storage) {
drive = libhal_drive_from_udi(ctx, udi);
if (libhal_drive_is_hotpluggable(drive) || libhal_drive_uses_removable_media(drive)) {
printf("Storage device added %s model %s\n",
libhal_drive_get_device_file(drive),
libhal_drive_get_model(drive));
}
libhal_drive_free(drive);
}
if(is_volume) {
volume = libhal_volume_from_udi(ctx, udi);
printf("Mount point = %s\n", libhal_volume_get_mount_point(volume));
libhal_volume_free(volume);
}
}
libhal_volume_from_udi, returns NULL.
Do you know any suitable way to detect the mount point of a storage device in C?
UPDATE
I have managed to find mount point of the device by searching /etc/mtab but there is still one little problem. I am assuming the device has one partition only.
How can I get the list of the partition on a storage device? So I can found mount points of each.

First, if you provide more details on what fails when you try to use the libhal function, you may get answers that help fix that issue. But to answer your question directly, a C program can determine what is mounted where by reading /etc/mtab. The format is fairly self-explanatory, each line typically lists the name of the storage device, the directory where it is mounted, the filesystem type, and mount options.
To map a specific directory in the filesystem to the mount point it belongs to it can be a little tricky -- remember if you're looping through /etc/mtab that mount points can have other mount points beneath them.
You may find looking at the source for programs that do this correctly, like "df" will help you get it right, or if your program doesn't need to look up this information often, you might decide to simply call popen(3) on a df command to do it for you. For example, the command:df /media/my-volume/some/path does a nice job displaying both the name of the storage device and the mount point where that device is mounted.

Related

How do I get a list of available wifi-connections? [duplicate]

I would like to get a list of the wireless networks available. Ideally this would be via some C call, but I don't mind if I have to kludge it with a system call. Even better if the required C call or program doesn't require some exotic 3rd party package.
The internet seems to suggest I use sudo iwlist <interface> scan which does seem to do the trick from the command line, but I'd rather not require root permissions. I only want to see the basics, not change anything.
It's pretty easy to do a scan in the command line. The man pages are your friend here (check out iwconfig and iwlist). But using the C interface is a little more difficult so I'll focus on that.
First of all, as other people have mentioned, definitely download out the wireless tools source code. All the documentation for the programming interface is in the .c files. As far as I can tell, there is no web documentation for the api. However, the source code is pretty easy to read through. You pretty much only need iwlib.h and iwlib.c for this question.
While you can use iw_set_ext and iw_get_ext, the libiw implements a basic scanning function iw_scan, from which you can extract most of the information that you need.
Here is a simple program to get the ESSID for all available wireless networks. Compile with -liw and run with sudo.
#include <stdio.h>
#include <time.h>
#include <iwlib.h>
int main(void) {
wireless_scan_head head;
wireless_scan *result;
iwrange range;
int sock;
/* Open socket to kernel */
sock = iw_sockets_open();
/* Get some metadata to use for scanning */
if (iw_get_range_info(sock, "wlan0", &range) < 0) {
printf("Error during iw_get_range_info. Aborting.\n");
exit(2);
}
/* Perform the scan */
if (iw_scan(sock, "wlan0", range.we_version_compiled, &head) < 0) {
printf("Error during iw_scan. Aborting.\n");
exit(2);
}
/* Traverse the results */
result = head.result;
while (NULL != result) {
printf("%s\n", result->b.essid);
result = result->next;
}
exit(0);
}
DISCLAIMER: This is just a demonstration program. It's possible for some results to not have an essid. In addition, this assumes your wireless interface is "wlan0". You get the idea.
Read the iwlib source code!
The Wireless Tools package -- of which iwlist is a part -- also contains a Wireless Tools Helper Library. You need to include iwlib.h and link with libiw.a (i.e. add -liw). Then look up the documentation for the iw_set_ext function. The SIOCSIWSCAN parameter will be of most use. For an example of how to use this interface, take a look at the KWifiManager source in the KDE library (see: Interface_wireless_wirelessextensions::get_available_networks method). Alternatively, you can also download the Wireless Tools source code and take a look at how the iwlib iw_set_ext function is also used for scanning in iwlist.c.
As for privileges, I imagine the process will need to run as root to perform the scan. I'd love to know if this could be done otherwise as well.
Since you are using Ubuntu 8.04 the libiw-dev package should be of use.
You can use nmcli which does not require root permissions or name of WIFI interface.
nmcli -t -f ssid dev wifi

How does the Linux Kernel know which file descriptor to write input events to?

I would like to know the mechanism in which the Linux Kernel knows which file descriptor (e.g. /dev/input/eventX) to write the input to. For example, I know that when the user clicks the mouse, an interrupt occurs, which gets handled by the driver and propagated to the Linux input core via input_event (drivers/input/input.c), which eventually gets written to the appropriate file in /dev/input/. Specifically, I want to know which source files I need to go through to see how the kernel knows which file to write to based on the information given about the input event. My goal is to see if I can determine the file descriptors corresponding to specific input event codes before the kernel writes them to the /dev/input/eventX character files.
You may go through two files:
drivers/input/input.c
drivers/input/evdev.c
In evdev.c, evdev_init() will call input_register_handler() to initialize input_handler_list.
Then in an input device driver, after initialize input_dev, it will call:
input_register_device(input_dev)
-> get device kobj path, like /devices/soc/78ba000.i2c/i2c-6/6-0038/input/input2
-> input_attach_handler()
-> handler->connect(handler, dev, id);
-> evdev_connect()
In evdev_connect(), it will do below:
1. dynamic allocate a minor for a new evdev.
2. dev_set_name(&evdev->dev, "event%d", dev_no);
3. call input_register_handle() to connect input_dev and evdev->handle.
4. create a cdev, and call device_add().
After this, you will find input node /dev/input/eventX, X is value of dev_no.

Autonomically sending a message from kernel-module to user-space application without relying on the invoke of input. from user-space

I will give a detailed exp of the program and lead to the issue regarding the use of netlink socket communication.
The last paragraph asks the actual question I need an answer for, so you might wanna start by peeking it first.
Disclaimer before I start:
- I have made an earlier search before asking here and did not find complete solution / alternative to my issue.
- I know how to initialize a module and insert it to kernel.
- I know to handle communication between module and user-space without using netlink sockets. Meaning using struct file_operations func pointers assignments to later be invoked by the module program whenever a user attempts to read/write etc. and answer to the user using copy_to_user / copy_from_user.
- This topic refers to Linux OS, Mint 17 dist.
- Language is C
Okay, so I am building a system with 3 components:
1. user.c : user application (user types commands here)
2. storage.c : storage device ('virtual' disk-on-key)
3. device.ko : kernel module (used as proxy between 1. and 2.)
The purpose of this system is to be able (as a user) to:
- Copy files to the virtual disk-on-key device (2) - like an "upload" from local directory that belongs to the user.
- Save files from the virtual device on local directory - like "download" from the device storage to the user directory.
Design:
Assuming programs (1),(2) are compiled and running + (3) has successfully inserted using the bash command ' sudo insmod device.ko ' , the following should work like this (simulation ofc):
Step 1 (in user.c) -> user types 'download file.txt'
Step 2 (in device.ko) -> the device recognizes the user have tried to 'write' to it (actually user just passing the string "download file.txt") and invokes the 'write' implementation of the method we set on struct file_operation earlier on module_init().
The device (kernel module) now passes the data (string with a command) to the storage.c application, expecting an answer to later be retrieved to the user.c application.
Step 3 (in storage.c) -> now, lets say this program performs a busy-wait loop of 'readmsg()' and that's how a request from module event is triggered and recognized, the storage device now recognizes that the module has sent a request (string with a command \ data). Now, the storage programs shall perform an implementation of some function 'X' to send the data requested using sendmsg() somewhere inside the function.
Now, here comes the issue.
Usually, on all of the examples I've looked on web, the communication between the kernel-module and a user-space (or the storage.c program in our case) using netlink is triggered by the user-space and not vice versa. Meaning that the sendmsg() function from the user-space invokes the 'request(struct sk_buff *skb)' method (which is set on the module_init() part as following:
struct netlink_kernel_cfg cfg = {
.input = request // when storage.c sends something, it invokes the request function
};
so when the storage.c performs something like:
sendmsg(sock_fd,&msg,0); // send a msg to the module
the module invokes and runs the:
static void request(struct sk_buff *skb) {
char *msg ="Hello from kernel";
msg_size=strlen(msg);
netlink_holder=(struct nlmsghdr*)skb->data;
printk(KERN_INFO "Netlink received msg payload:%s\n",(char*)nlmsg_data(netlink_holder));
pid = netlink_holder->nlmsg_pid; // pid of sending process
skb_out = nlmsg_new(msg_size,0);
if(!skb_out){
printk(KERN_ERR "Failed to allocate new skb\n");
return;
}
netlink_holder=nlmsg_put(skb_out,0,0,NLMSG_DONE,msg_size,0); // add a new netlink message to an skb. more info: http://elixir.free-electrons.com/linux/v3.2/source/include/net/netlink.h#L491
NETLINK_CB(skb_out).dst_group = 0; // not in multicast group
strncpy(nlmsg_data(netlink_holder),msg,msg_size); // assign data as char* (variable msg)
result=nlmsg_unicast(sock_netlink,skb_out,pid); // send data to storage. more info: http://elixir.free-electrons.com/linux/latest/source/include/net/netlink.h#L598
if(result<0)
printk(KERN_INFO "Error while sending bak to user\n");
}
and from all that big chunk, the only thing that im interesting in is actually doing this:
result=nlmsg_unicast(sock_netlink,skb_out,pid); // send data to storage.
BUT I can't use nlmsg_unicast() without having the strcut sk_buff* which is provided automatically for me whenever there's an invoke from storage.c !
To sum up everything:
How do I send a msg from the device.ko (kernel module) to the user-space withtout having to wait for request to invoke / rely on the provided strcut sk_buff parameter from the earlier shown 'request()' method ?
Hope this sums up the point.
Thanks.
The only question here is that you need the user-space program connected to kernel-space first to get the pid of your user-program.
After get the pid, you can manually construct the skb_out and send it out through netlink_unicast or nlmsg_unicast.
The pid is always needed, you can set it as static and let your user-space program connect to your device.ko to make a long-maintained link.
Although this question is asked at 2017, I believe OP has already found the answer :D

Close device/socket in VxWorks

Is there a way to close the device/socket in VxWorks programmatically?
Meaning say I have the devices /tyco/0, /tyco/1 and /tyco/2 and I want to close/shutdown /tyco/1 and /tyco/2.
I would like to do something like remove("/tyco/1"). Something that would prevent even an open("/tyco/1") call later on in the code or from an outside source from opening the socket.
All devices available to VxWorks are part of the device list. The device list is accessible using the iosLib.
I've used the following code a lot to remove devices to generate errors in order to test my programs:
DEV_HDR *pDevice;
pDevice = iosDevFind("/xyz", NULL);
if (pDevice != NULL)
{
iosDevDelete(pDevice);
}
This works for all devices listed by the devs command which in your case will also work for "/tyco". I doubt that you can inhibit open calls to "/tyco/1" and "/tyco/2" but allow calls to "/tyco/0" using that method since it works on "devices".
If "/tyco/0" is your serial interface to the VxWorks shell then the method from above will work. Because removing a device from the device list will cause all following open calls to that device to fail but will not close already opened devices...

How to create multiple network namespace from a single process instance

I am using following C function to create multiple network namespaces from a single process instance:
void create_namespace(const char *ns_name)
{
char ns_path[100];
snprintf(ns_path, 100, "%s/%s", "/var/run/netns", ns_name);
close(open(ns_path, O_RDONLY|O_CREAT|O_EXCL, 0));
unshare(CLONE_NEWNET);
mount("/proc/self/ns/net", ns_path, "none", MS_BIND , NULL);
}
After my process creates all the namspaces and I add a tap interface to any of the one network namespace (with ip link set tap1 netns ns1 command), then I actually see this interface in all of the namespaces (presumably, this is actually a single namespace that goes under different names).
But, if I create multiple namespaces by using multiple processes, then everything is working just fine.
What could be wrong here? Do I have to pass any additional flags to the unshare() to get this working from a single process instance? Is there a limitation that a single process instance can't create multiple network namespaces? Or is there a problem with mount() call, because /proc/self/ns/net is actually mounted multiple times?
Update:
It seems that unshare() function creates multiple network namespaces correctly, but all the mount points in /var/run/netns/ actually reference to the first network namespace that was mounted in that direcotry.
Update2:
It seems that the best approach is to fork() another process and execute create_namespace() function from there. Anyway, I would be glad to hear a better solution that does not involve fork() call or at least get a confirmation that would prove that it is impossible to create and manage multiple network namespaces from a single process.
Update3:
I am able to create multiple namespaces with unshare() by using the following code:
int main() {
create_namespace("a");
system("ip tuntap add mode tap tapa");
system("ifconfig -a");//shows lo and tapA interface
create_namespace("b");
system("ip tuntap add mode tap tapb");
system("ifconfig -a");//show lo and tapB interface, but does not show tapA. So this is second namespace created.
}
But after the process terminates and I execute ip netns exec a ifconfig -a and ip netns exec b ifconfig -a it seems that both commands were suddenly executed in namespace a. So the actual problem is storing the references to the namespaces (or calling mount() the right way. But I am not sure, if this is possible).
Network Namespaces are, by design, created with a call to clone, and it can be modified after by unshare. Take note that even if you do create a new network namespace with unshare, in fact you just modify network stack of your running process. unshare is unable to modify network stack of other processes, so you won't be able to create another one only with unshare.
In order to work, a new network namespace needs a new network stack, and so it needs a new process. That's all.
Good news is that it can be made very lightweight with clone, see:
Clone() differs from the traditional fork() system call in UNIX, in
that it allows the parent and child processes to selectively share or
duplicate resources.
You are able to divert only on this network stack (and avoid memory space, table of file descriptors and table of signal handlers). Your new network process can be made more like a thread than a real fork.
You can manipulate them with C code or with Linux Kernel and/or LXC tools.
For instance, to add a device to new network namespace, it's as simple as:
echo $PID > /sys/class/net/ethX/new_ns_pid
See this page for more info about CLI available.
On the C-side, one can take a look at lxc-unshare implementation. Despite its name it uses clone, as you can see (lxc_clone is here). One can also look at LTP implementation, where the author has chosen to use fork directly.
EDIT: There is a trick that you can use to make them persistent, but you will still need to fork, even temporarily.
Take a look at this code of ipsource2 (I have removed error checking for clarity):
snprintf(netns_path, sizeof(netns_path), "%s/%s", NETNS_RUN_DIR, name);
/* Create the base netns directory if it doesn't exist */
mkdir(NETNS_RUN_DIR, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
/* Create the filesystem state */
fd = open(netns_path, O_RDONLY|O_CREAT|O_EXCL, 0);
[...]
close(fd);
unshare(CLONE_NEWNET);
/* Bind the netns last so I can watch for it */
mount("/proc/self/ns/net", netns_path, "none", MS_BIND, NULL)
If you execute this code in a forked process, you'll be able to create new network namespace at will. In order to delete them, you can simply umount and delete this bind:
umount2(netns_path, MNT_DETACH);
if (unlink(netns_path) < 0) [...]
EDIT2: Another (dirty) trick would be simply to execute "ip netns add .." cli with system.
You only have to bind mount /proc/*/ns/* if you need to access these namespaces from another process, or need to get handle to be able to switch back and forth between the two. It is not needed to use multiple namespaces from a single process.
unshare does create new namespace.
clone and fork by default do not create any new namespaces.
there is one "current" namespace of each kind assigned to a process. It can be changed by unshare or setns. Set of namespaces (by default) is inherited by child processes.
Whenever you do open(/proc/N/ns/net), it creates inode for this file,
and all subsequent open()s will return file that is bound to the
same namespace. Details are lost in the depths of kernel dentry cache.
Also, each process has only one /proc/self/ns/net file entry, and
bind mount does not create new instances of this proc file.
Opening those mounted files are exactly the same as opening
/proc/self/ns/net file directly (which will keep pointing to the
namespace it pointed to when you first opened it).
It seems that "/proc/*/ns" is half-baked like this.
So, if you only need 2 namespaces, you can:
open /proc/1/ns/net
unshare
open /proc/self/ns/net
and switch between the two.
For more that 2 you might have to clone(). There seems to be no way to create more than one /proc/N/ns/net file per process.
However, if you do not need to switch between namespaces at runtime, or to share them with other processes, you can use many namespaces like this:
open sockets and run processes for main namespace.
unshare
open sockets and run processes for 2nd namespace (netlink, tcp, etc)
unshare
...
unshare
open sockets and run processes for Nth namespace (netlink, tcp, etc)
Open sockets keep reference to their network namespace, so they will not be collected until sockets are closed.
You can also use netlink to move interfaces between namespaces, by sending netlink command on source namespace, and specifying dst namespace either by PID or namespace FD (the later you don't have).
You need to switch process namespace before accessing /proc entries that depend on that namespace. Once "proc" file is open, it keeps reference to the namespace.

Resources