Close device/socket in VxWorks - c

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...

Related

change file descriptor without re-initializing the handle of uv_poll_t type

I have an application project running on Linux environment, which includes libuv and another third-party library, the third-party library provides APIs for starting a TCP connection to remote server (say xxx_connect()) and getting file descriptor of the active connection (say xxx_get_socket()) . So far I managed to get valid file descriptor from xxx_get_socket() after xxx_connect() completed successfully, and initialize uv_poll_t handle with that file descriptor in my program.
Currently I am working on reconnecting function, after reconnecting the same server (by running xxx_connect() again), xxx_get_socket() returns different file descriptor, that means it is necessary to update io_watcher.fd member of a uv_poll_t handle to receive data in the new active connection.
AFAIK uv_poll_init() internally invokes uv__io_check_fd() , uv__nonblock() and uv__io_init() , it seems possible to modify io_watcher.fd of a uv_poll_t handle without closing the handle and then initializing it again (see sample code below), which has extra latency. However I'm not sure if it is safe to do so, I don't know whether io_watcher.fd member of a uv_poll_t handle is referenced elsewhere in libuv (e.g. uv_run()) which makes thing more complex. Is my approach feasible or should I re-initialize the uv_poll_t handle in such case ? Appreciate any feedback.
Possible approach , simplified sample code :
int uv_poll_change_fd( uv_poll_t *handle, int new_fd ) {
if (uv__fd_exists(handle->loop, new_fd))
// ..... some code ....
err = uv__io_check_fd(handle->loop, new_fd);
if(err)
// ..... some code ....
err = uv__nonblock(new_fd, 1);
// ..... some code ....
handle->io_watcher.fd = new_fd;
}

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.

Get signal level of the connected WiFi network

Using wpa_supplicant 2.4 on ARM Debian.
Is there a way to get signal level, in decibels or percents, of the wireless network I’m currently connected to?
STATUS command only returns the following set of values: bssid, freq, ssid, id, mode, pairwise_cipher, group_cipher, key_mgmt, wpa_state, ip_address, p2p_device_address, address, uuid
I can run SCAN afterwards, wait for results and search by SSID. But that’s slow and error-prone, I'd like to do better.
The driver should already know that information (because connected, and adjusting transmit levels for energy saving), is there a way to just query for that?
This question is not about general computing hardware and software. I'm using wpa_supplicant through a C API defined in wpa_ctrl.h header, interacting with the service through a pair of unix domain sockets (one for commands, another one for unsolicited events).
One reason I don’t like my current SCAN + SCAN_RESULT solution, it doesn’t work for hidden SSID networks. Scan doesn’t find the network, therefore I’m not getting signal level this way. Another issue is minor visual glitch at application startup. My app is launched by systemd, After=multi-user.target. Unless it’s the very first launch, Linux is already connected to Wi-Fi by then. In my app’s GUI (the product will feature a touch screen), I render a phone-like status bar, that includes WiFi signal strength icon. Currently, it initially shows minimal level (I know it's connected because STATUS command shows SSID), only after ~1 second I’m getting CTRL-EVENT-SCAN-RESULTS event from wpa_supplicant, run SCAN_RESULT command and update signal strength to the correct value.
On the API level my code is straightforward. I have two threads for that, both call wpa_ctrl_open, the command thread calls wpa_ctrl_request, the event thread has an endless loop that calls poll passing wpa_ctrl_get_fd() descriptor and POLLIN event mask, followed by wpa_ctrl_pending and wpa_ctrl_recv.
And here's the list of files in /sys/class/net/wlan0:
./mtu
./type
./phys_port_name
./netdev_group
./flags
./power/control
./power/async
./power/runtime_enabled
./power/runtime_active_kids
./power/runtime_active_time
./power/autosuspend_delay_ms
./power/runtime_status
./power/runtime_usage
./power/runtime_suspended_time
./speed
./dormant
./name_assign_type
./proto_down
./addr_assign_type
./phys_switch_id
./dev_id
./duplex
./gro_flush_timeout
./iflink
./phys_port_id
./addr_len
./address
./operstate
./carrier_changes
./broadcast
./queues/rx-0/rps_flow_cnt
./queues/rx-0/rps_cpus
./queues/rx-1/rps_flow_cnt
./queues/rx-1/rps_cpus
./queues/rx-2/rps_flow_cnt
./queues/rx-2/rps_cpus
./queues/rx-3/rps_flow_cnt
./queues/rx-3/rps_cpus
./queues/tx-0/xps_cpus
./queues/tx-0/tx_maxrate
./queues/tx-0/tx_timeout
./queues/tx-0/byte_queue_limits/limit
./queues/tx-0/byte_queue_limits/limit_max
./queues/tx-0/byte_queue_limits/limit_min
./queues/tx-0/byte_queue_limits/hold_time
./queues/tx-0/byte_queue_limits/inflight
./queues/tx-1/xps_cpus
./queues/tx-1/tx_maxrate
./queues/tx-1/tx_timeout
./queues/tx-1/byte_queue_limits/limit
./queues/tx-1/byte_queue_limits/limit_max
./queues/tx-1/byte_queue_limits/limit_min
./queues/tx-1/byte_queue_limits/hold_time
./queues/tx-1/byte_queue_limits/inflight
./queues/tx-2/xps_cpus
./queues/tx-2/tx_maxrate
./queues/tx-2/tx_timeout
./queues/tx-2/byte_queue_limits/limit
./queues/tx-2/byte_queue_limits/limit_max
./queues/tx-2/byte_queue_limits/limit_min
./queues/tx-2/byte_queue_limits/hold_time
./queues/tx-2/byte_queue_limits/inflight
./queues/tx-3/xps_cpus
./queues/tx-3/tx_maxrate
./queues/tx-3/tx_timeout
./queues/tx-3/byte_queue_limits/limit
./queues/tx-3/byte_queue_limits/limit_max
./queues/tx-3/byte_queue_limits/limit_min
./queues/tx-3/byte_queue_limits/hold_time
./queues/tx-3/byte_queue_limits/inflight
./tx_queue_len
./uevent
./statistics/rx_fifo_errors
./statistics/collisions
./statistics/rx_errors
./statistics/rx_compressed
./statistics/rx_dropped
./statistics/tx_packets
./statistics/tx_errors
./statistics/rx_missed_errors
./statistics/rx_over_errors
./statistics/tx_carrier_errors
./statistics/tx_heartbeat_errors
./statistics/rx_crc_errors
./statistics/multicast
./statistics/tx_fifo_errors
./statistics/tx_aborted_errors
./statistics/rx_bytes
./statistics/tx_compressed
./statistics/tx_dropped
./statistics/rx_packets
./statistics/tx_bytes
./statistics/tx_window_errors
./statistics/rx_frame_errors
./statistics/rx_length_errors
./dev_port
./ifalias
./ifindex
./link_mode
./carrier
You can get the signal level of the connected wifi by wpa_supplicant cmd SIGNAL_POLL
The wpa_supplicant would return:
RSSI=-60
LINKSPEED=867
NOISE=9999
FREQUENCY=5745
The value of the RSSI is the signal level.
You can get the signal level of the connected wifi by wpa_supplicant cmd BSS <bssid>.
About the bssid of the connected wifi, you can get from wpa_supplicant cmd STATUS.
https://android.googlesource.com/platform/external/wpa_supplicant_8/+/622b66d6efd0cccfeb8623184fadf2f76e7e8206/wpa_supplicant/ctrl_iface.c#1986
For iw compatible devices:
Following command gives the current station(aka AP) signal strength:
iw dev wlp2s0 station dump -v
If you need C API, just dig the source code of iw.
After a quick glance, the function you need is here
For broadcom devices, try search broadcom wl. It is close source, don't know if C API is provided.

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