How to set total length of TCP option in Linux kernel? - c

I'm trying to add a new TCP option inside Linux kernel. However, I find that my new option cannot coexist with other options because there are no enough spaces in the option field for it. I get the warning from wireshark as "option goes past end of options".
So I'm wondering how I can extend the length of the whole TCP option field?
In tcp_parse_options() of tcp_input.c, I find such statement:
int length = (th->doff * 4) - sizeof(struct tcphdr);
And the while loop to parse options starts with while (length > 0). However, no matter how I increase the value of th->doff in tcp_make_synack() of tcp_output.c, the problem remains. I also suspect this is because I add the option in SYN pakcet while this function is for SYN-ACK. But I cannot find similar functions such as tcp_make_synack()....
Does anyone have any insights of this problem?
Thanks!

Related

Add TCP Options

Is there any easy & fast way to add TCP options to the SKB packet like Window scaling factor or Time stamp with C on netfilter.
Or if any body has example it would be perfect to see.
Thank you
One of the fastest way is by using sysctl and following are various options, but as you are interested in window size and timestamp are below:
net.ipv4.tcp_slow_start_after_idle
net.ipv4.tcp_timestamps
The command to control them is:
sudo sysctl -w <option=123>
Otherwise you can control it programatically like the way timestamp is controlled either in software or hardware in this guide.

How to execute net.exe from Windows Runtime in C?

To introduce my problem, I'm currently working on a project to remotely shut down stationary PCs via Siemens S7 PLC. Those PCs are used for an experimental manufactoring line for relays at my university. The principle is quiet simple, the PLC sends the IP of a computer via UDP to a special "always on" PC with monitoring functions on which a UDP server listens for packets (this PC starts up together with the manufactoring line; OS is Windows 10; the server is written in C). If it receives an UDP packet, it triggers a net use command followed by a shutdown command to that specific IP. This works just fine, if the server.exe is started manually. The goal is to get the server working when it's automatically started with e.g. the taskplaner. Exactly this is the main issue here, it's not working as background task. It receives the packets (I tested it) but then nothing happens, no computer shuts down. So I guessed it must be the net use or the shutdown command. At first I tried to set up the net use with a system()call:
char command[100] = { 0 };
snprintf(command, sizeof(command), "#NET USE \\\\%s\\IPC$ %s /USER:%s", ip, pw, usr);
system(command);
As this won't work I found following statement for system()on the Windows API reference page:
This API cannot be used in applications that execute in the Windows Runtime.
So I figured I had to find an alternative, which leads me to my next try with the ShellExecute() function. It seemed like there are no problems concerning the execution out of the runtime, cause I could't find any word about it at the reference page. I tried:
char programpath[100] = "C:\\Windows\\System32\\net.exe";
char cmdline[100] = { 0 };
snprintf(cmdline, sizeof(cmdline), "Use \\\\%s\\IPC$ %s /USER:%s", ip, pw, usr);
ShellExecute(NULL, "open", programpath, cmdline, NULL, SW_HIDE);
But nope, won't work either from the background. When I asked my prof about it, he said he is more into Linux, so he could only guess that there might be a problem with the permissions. He meant that my server has possibly no rights to open those two programs, when calling them as background process. But even after a long time of investigating through the internet, I can't find a proper solution which fits to my problem.

STM32 USB VCP (Virtual Com Port)

I generated a code for "stm32f103c8t6" with CubeMX for USB VCP, when I add "CDC_Transmit_FS" command to send data, the port isn't recognized by windows10!
what should I do? Here is the code which is compiled without error:
#include "stm32f1xx_hal.h"
#include "usb_device.h"
#include "usbd_cdc_if.h"
int main(void)
{
uint8_t Text[] = "Hello\r\n";
while (1)
{
CDC_Transmit_FS(Text,6); /*when commented the port is recognized*/
HAL_Delay(1000);
}
}
There are three things you need to check in my experience:
startup_stm32f405xx.s --> Increase the Heap size. I use heap size 800 and stack size 800 as well.
usbd_cdc_if.c --> APP_RX_DATA_SIZE 64 and APP_TX_DATA_SIZE 64
usbd_cdc_if.c --> add below code to the CDC_Control_FS() function
Code:
case CDC_SET_LINE_CODING:
tempbuf[0]=pbuf[0];
tempbuf[1]=pbuf[1];
tempbuf[2]=pbuf[2];
tempbuf[3]=pbuf[3];
tempbuf[4]=pbuf[4];
tempbuf[5]=pbuf[5];
tempbuf[6]=pbuf[6];
break;
case CDC_GET_LINE_CODING:
pbuf[0]=tempbuf[0];
pbuf[1]=tempbuf[1];
pbuf[2]=tempbuf[2];
pbuf[3]=tempbuf[3];
pbuf[4]=tempbuf[4];
pbuf[5]=tempbuf[5];
pbuf[6]=tempbuf[6];
break;
and define the uint8_t tempbuf[7]; in the user private_variables section.
Without the increased heap size, Windows does not react at all.
Without the point 3, Windows will send the baud rate information and then read the baud rate, expecting to get back the same values. Since you do not return any values, the virtual com port remains as driver-not-loaded.
If you do all of that, the Windows 10 out-of-the-box VCP driver can be used. No need to install the very old ST VCP driver on your system.
PS: I read somewhere turning on VSense makes problems, too. Don't know, I have not configured it and all works like a charm.
Put delay before CDC_Transmit_FS call - it will wait for the initiatialization. Your code should be like this
int main(void)
{
uint8_t Text[] = "Hello\r\n";
HAL_Delay(1000);
while (1)
{
CDC_Transmit_FS(Text,6); /*when commented the port is recognized*/
HAL_Delay(1000);
}
}
I had similar issue. I couldn't connect to a port and the port appears as just "virtual com port". I added while loop to wait for USBD_OK from CDC_Transmit_FS. Then it stars work even with out it or a delay after init function. I am not sure what the issue was.
while(CDC_Transmit_FS((uint8_t*)txBuf, strlen(txBuf))!=USBD_OK)
{
}
you may have to install driver to get device recognized as com port
you can get it from st site
if not installed the device is listed with question or exclamation mark on device manager
note that you cannot send until device get connected to host!
not sure that CubeMX CDC_Transmit_FS is checking for this
also instead of delay to resend you shall check the CDC class data "TXSstate"
is 0 mean tx is over.
I know it's a bit late, but I stumbled upon this post and it was extremely helpful.
Here is what I needed to do:
do the Line-Coding (I think only necessary on Windows-Systems)
increase Heap (Stack was left at default 0x200)
Here is what wasn't necessary for me (on a STM32F405RGT6 Chip):
change APP_RX_DATA_SIZE / APP_TX_DATA_SIZE (left it at 2048)
add a delay befor running CDC_Tranmit_FS()
Also some things to consider that happened to me in the past:
be sure to use a USB-Cable with data lines (most charging-cables don't have them)
double check the traces/connections if you use a custom board

Specifying new option for hop by hop extension header IPv6?

I have been trying to get an answer for this for sometime now but not been able to find it.
Is there a way that I can specify a new option value for the hop by hop extension header in IPv6, so that I can parse the value in the user space rather than the kernel parsing it?
The kernel when tries to parse the value, sends me an ICMP reply stating parameter not recognized for that value in the header.
I'm wondering if there should be a way to deploy and test new options in IPv6 extension header without writing handlers for them as LKM.
There isn't a lot available on the web for IPv6, so any help from IPv6 experts would be great!
RFC 2460 mentions this. I assume you can create a new option type for testing any new applications:
Mindful of the need for compatibility with existing IPv6 deployments,
new IPv6 extension headers MUST NOT be created or specified, unless
no existing IPv6 Extension Header can be used by specifying a new
option for that existing IPv6 Extension Header. Any proposal to
create or specify a new IPv6 Extension Header MUST include a detailed
technical explanation of why no existing IPv6 Extension Header can be
used in the Internet-Draft proposing the new IPv6 Extension Header.
As for "The kernel when tries to parse the value, sends me an ICMP reply ..." you mentioned, by "kernel" I assume you means a remote ipv6 node ( either router or destination host ). Then you might set the "Option Type" wrong way in your egress packet sending by raw-socket.
As RFC 2460 says:
The Option Type identifiers are internally encoded such that their highest-order two bits specify the action that must be taken if the processing IPv6 node does not recognize the Option Type:
00, 01, 10, 11 ....
--- I guess you fill in "10" or "11", you could fill in "00"

Set wireless channel using netlink API

I am developing a WiFi tool in Ubuntu Linux 12.04 environment and I need to switch the WiFi interface between different channels.
Currently I found the solution in Wireshark source code ws80211_utils.c in function called ws80211_set_freq but I do not know how to implement it into my source code and which libs to include and how to compile so I could test it.
The problem is that there are too many arguments and flags you have to use. Also, this is the first time I develop a netlink wifi tool.
If there are any good manuals available where to start and how to use netlink calls for WiFi please provide me with the link.
Thanks a lot i advance!
In current Linux versions, nl80211 is the right way to "talk" to the wireless subsystem. Be aware that you cannot arbitrarily set a channel with every driver and every operating mode (master, client, monitor etc.) Some drivers allow a channel change only when the corresponding interface is "down". In modes such as client ("managed"), the channel cannot be set at all because it is defined by the access point.
Also note that not all wireless device drivers use mac80211/cfg80211. For those drivers not using it, you either have to use the old wireless extensions API or (even worse) a driver-specific proprietary API.
Sadly, there seems to be no up-to-date and complete documentation of the nl80211 interface. Please correct me if I am wrong!
Your approach of looking into the source code of other programs seems to be a reasonable way. You could also use the source code of the iw command line utility. iw has an option to set the channel:
$ iw --help
Usage: iw [options] command
Options:
--debug enable netlink debugging
--version show version (3.2)
Commands:
…
dev <devname> set channel <channel> [HT20|HT40+|HT40-]
…
In iw's phy.c, line 91ff. you can find the code called when iw wlan0 set channel is executed. However, this code is definitely not easy to read. It looks like the
NL80211_CMD_SET_WIPHYcommand in conjunction with the NL80211_ATTR_WIPHY_FREQ attribute is the way to go.
In this SO answer you can find a skeleton program for using nl80211. Also, the code of Aircrack-ng (src/osdep/linux.c, function linux_set_channel_nl80211) could act as a blueprint.
The accepted answer is currently correct, but there's no example code posted yet which solves the OP's question (even if nearly 4 years late), so I thought I would add this here for any future search engine users. It's adapted from this SO question and the specific Aircrack-ng file (/src/aircrack-osdep/linux.c, line 1050) that were both previously mentioned.
#include <net/if.h>
#include <netlink/netlink.h>
#include <netlink/genl/genl.h>
#include <netlink/genl/ctrl.h>
#include <linux/nl80211.h>
int main(int argc, char *argv[])
{
/* The device's name and the frequency we wish to set it to. */
char *device = "wlan1";
int frequencyMhz = 2442;
/* Create the socket and connect to it. */
struct nl_sock *sckt = nl_socket_alloc();
genl_connect(sckt);
/* Allocate a new message. */
struct nl_msg *mesg = nlmsg_alloc();
/* Check /usr/include/linux/nl80211.h for a list of commands and attributes. */
enum nl80211_commands command = NL80211_CMD_SET_WIPHY;
/* Create the message so it will send a command to the nl80211 interface. */
genlmsg_put(mesg, 0, 0, genl_ctrl_resolve(sckt, "nl80211"), 0, 0, command, 0);
/* Add specific attributes to change the frequency of the device. */
NLA_PUT_U32(mesg, NL80211_ATTR_IFINDEX, if_nametoindex(device));
NLA_PUT_U32(mesg, NL80211_ATTR_WIPHY_FREQ, frequencyMhz);
/* Finally send it and receive the amount of bytes sent. */
int ret = nl_send_auto_complete(sckt, mesg);
printf("%d Bytes Sent\n", ret);
nlmsg_free(mesg);
return EXIT_SUCCESS;
nla_put_failure:
nlmsg_free(mesg);
printf("PUT Failure\n");
return EXIT_FAILURE;
}
Compile this with gcc main.c $(pkg-config --cflags --libs libnl-3.0 libnl-genl-3.0).
Once executed, check the frequency/channel of your device with e.g. iw wlan1 info or iwconfig. There's no serious error checking here, so all you will notice is if the message was sent or not. Hopefully this helps anyone like me making the transition from Wireless Extensions to cfg80211 and nl80211.

Resources