How do I get PID from socket port on Windows? - c

Given a socket port how do you find the process ID (process name) of the process on Windows 10 that uses this port? I am aware of netstat command but I would like to do it with C code only.

How about there, it appears there's a way: the IP Helper library.
Ref: https://learn.microsoft.com/en-us/windows/win32/iphlp/ip-helper-start-page
I haven't used it for this, but it's clearly going down the right road by providing everything you need to basically roll your own netstat.exe.
The low-level object that contains all the info is MIB_TCPROW2, which has the local and remote address + port, plus dwOwningPid. So we know there's a way.
Drilling down we ultimately need the GetTcpTable2() call, and Microsoft's web page helpfully has what appears to be fully-functional C code to do all this yourself.
https://learn.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-gettcptable2
Finding this was the best surprise of my day!

Related

Retrieving the printer status from the Brother TD-4100N printer in a network environment

We're switching to a system where our shippers need to put barcodes with our article IDs on the products they're sending henceforth. Our management is willing to lend them Brother TD-4100N label printers under the condition that they do not use it for other purposes other than printing our barcodes, and now I'm tasked with programming an interface that allows them to print our barcodes.
Their core competency however lies in shipping management, not IT administration, and so I have to keep things simple and platform-independent - or at least as platform-independent as possible. The idea here is to be able to plug in one of those printers via ethernet without any kind of setup - as simple as possible. No drivers, no nothing, keep it simple, stupid. An ethernet port and sockets is all I wanna use. And with this specific model having an ethernet port and accepting ESC/P codes that shouldn't be so hard, right?
After spending a week with one test machine I've learnt enough about the ESC/P codes and Brother's proprietary extensions (at least they claim them to be) to write a little framework in C. Printing barcodes in the required format (Code128) doesn't pose a problem in and of itself, but the bookkeeping around it does; I'm at my third manual at this point that claims that simply sending the command "\x1B\x69\x53" (ESC i S) should cause the printer to send me a 32-byte record of its current status, but for some reason the printer simply doesn't want to send me how it's doing:
char buffer_send[] = "x1B\x69\x53";
send(sock_jet,buffer_send,sizeof(buffer_send) - 1,0);
char buffer[32];
memset(buffer,0,sizeof(buffer));
recv(sock_jet,buffer,sizeof(buffer),0);
fprintf
(
stderr,
"%02x%02x%02x%02x%02x%02x%02x%02x\n",
buffer[0],buffer[1],buffer[2],buffer[3],buffer[4],buffer[5],buffer[6],buffer[7]
);
fprintf
(
stderr,
"%02x%02x%02x%02x%02x%02x%02x%02x\n",
buffer[8],buffer[9],buffer[10],buffer[11],buffer[12],buffer[13],buffer[14],buffer[15]
);
fprintf
(
stderr,
"%02x%02x%02x%02x%02x%02x%02x%02x\n",
buffer[16],buffer[17],buffer[18],buffer[19],buffer[20],buffer[21],buffer[22],buffer[23]
);
fprintf
(
stderr,
"%02x%02x%02x%02x%02x%02x%02x%02x\n",
buffer[24],buffer[25],buffer[26],buffer[27],buffer[28],buffer[29],buffer[30],buffer[31]
);
This code simply stalls for some time until timeout hits or whatever, and recv doesn't write any data into my buffer:
0000000000000000
0000000000000000
0000000000000000
0000000000000000
And I'm apparently not the only one with such a problem. This Ruby Python package (https://pypi.org/project/brotherprint/#files) claims to be specifically catered for Brother printers, but I never see them receive any data (in brotherprint/brotherprint.py at least). In fact I don't even see them spelling "receive" correctly.
On SO (operating printer with php socket programming) someone tried to do the same in PHP I'm trying to do in C - and they had the exact same problem as I'm having, with the printer refusing to give them status data. The solution seems to involve switching from port 9100 to port 515 and using a different protocol, and while I've seen port 515 to be open on the printer I've never seen any output from that printer, on paper or on the socket. At this point I'd contact the Brother support, but I'm already having another ticket open because another printer of their's does seem to have major problems sending status reports back to CUPS.
I've tried adding a NUL byte at the end of my payload, in case the printer is waiting for a page feed, but that didn't do the trick either. Again: printing barcodes to the damn thing works, so IP, port, and connection work at least to a degree - but receiving a status report doesn't.
The strace from my program:
connect(3, {sa_family=AF_INET, sin_port=htons(9100), sin_addr=inet_addr("192.168.XXX.XXX")}, 16) = 0
sendto(3, "\33iS", 3, 0, NULL, 0) = 3
recvfrom(3, <blocks here for minutes> "", 32, 0, NULL, NULL) = 0
write(2, "0000000000000000\n", 170000000000000000
) = 17
write(2, "0000000000000000\n", 170000000000000000
) = 17
write(2, "0000000000000000\n", 170000000000000000
) = 17
write(2, "0000000000000000\n", 170000000000000000
) = 17
close(3)
And the main manual that I'm using: https://download.brother.com/welcome/docp000579/cv_td4000_eng_escp_120.pdf (search for "ESC i S").
OK, so I actually got a response from the Japanese Brother support. And there is so much wrong with that response that I may come off as rambling a little right now.
Brother insists that
ESC/P is not supposed to be for bi-directional communications.
, which is a load of steaming BS seeing as Brother MADE their implementation bi-directional. That is what the documentation says! Read it for yourself in the ESC/P documentation they provide.
Requests the printer status.
The printer status comprises 32 bytes.
So I've already caught them either lying or being incompetent.
The next lie/being incompetent is:
Namely what you have reported is within our specifications.
I'd have LOVED to actually see those specifications they've quoted here. The only thing I've found so far was section 5 "Additional Functions" in my manual, which has a paragraph called "ESC/P commands" in which they link to the aforementioned ESC/P manual. This manual specifically states:
This information is provided assuming that the user has full understanding of the operating system being used and basic mastery of RS-232C, USB or Ethernet in a developer's environment.
In section 8 "Using Interface Cables" they state that RS-232C (serial) and RJ-45 (ethernet) cables are not standard accessories, and that it's not possible to connect a RS-232C and a USB cable to the same printer at the same time. Then there are some installation instructions on MS Windows computers, and that's about it.
Their FAQ doesn't mention anything (https://www.brother.co.jp/eng/dev/command/faq/index.aspx) except for using SNMP (which doesn't work on this printer because Port 161/162 are not even open), and their network reference is just as mute (https://download.brother.com/welcome/docp000592/cv_td2130n_eng_net.c.pdf - not one mentioning of ESC/P). I'm seriously wondering if I'm too stupid to find this, or if they pulled that one out of their ar**s just to not have to deal with this.
And don't tell me they wouldn't do this. This printer also runs a webserver on port 80 that has a confirmed secvuln (https://threatpost.com/tag/debut-embedded-web-server/).
But then they actually get to the core of the issue here:
Besides, our specification never ruturns when using Netwrokd even if an error does not happen
This little part of Engrish here is probably supposed to mean:
Even if an error occurs our hardware does not send status reports over ethernet.
, which would explain why the printer remains silent. However I don't believe this is part of their specification, which I couldn't even find; I believe they got caught with their pants down yet again and refuse to acknowledge it. It shouldn't make any difference how you connect to the machine - ethernet, serial, or USB - as long as the transport layer works, which obviously is the case since I can send other commands to the printer. However this is supposed to be used on different machines on the same network. Why do they even have an ethernet port if the firmware is unable to send a status report? Who came up with this idea?
I can honestly only discourage people from getting Brother devices. This is the second printer I've seen from this company that simply doesn't work over ethernet, and what good is a printer if you cannot query its status to determine if you're to send a job to it? And they sell those unreliable machines for 600 € apiece.

Get node name given to a USB by ACM Driver

I have two usb devices that are recognized by the ACM driver and I’m developing a program in C to communicate with them. As the command for each one are different, I need to know the name given for each one (usb/acm/X).
How can I get this name given the vendorId and productId? I have tried parsing dmesg text but in some cases I may have the two lines “ttyACMX: USB ACM device” one after the other.
I could parse the order each device shows its name in dmesg and take the same number in the “ttyACMX” but this force me to parse also the disconnections messages and all becomes a bit dirty.
I’ve seen that the information I need is in the structure tty_driver created for each device and I’m sure I can have this information easier than parsing dmesg.
Can someone point me out int the right direction?
libudev (C) might be a solution, also have a look at the source of ModemManager daemon (C, glib based)
Use libudev or some higher-level library like gudev (GLib-based libudev). Don't use ModemManager unless your devices are really mobile broadband (2G/3G/4G) modems.
I found this thread to be helpful: http://forum.pololu.com/viewtopic.php?f=16&t=6741
You can make a udev rule file in /etc/udev/rules.d that has a rule like this:
KERNEL=="ttyACM0", SUBSYSTEM=="tty", SUBSYSTEMS=="usb",
ATTRS{idVendor}=="1ffb", ATTRS{idProduct}=="008c",
ATTRS{serial}=="00053419", MODE="0666", SYMLINK+="TTYS_002"
I think this will make a device named /dev/TTYS_002 when you plug in a CDC ACM device that has the specified vendor ID, product ID, and serial number.

How to check if port is available

Is there an API function on Linux (kernel 2.6.20) which can be used to check if a given TCP/IP port is used - bound and/or connected ?
Is bind() the only solution (binding to the given port using a socket with the SO_REUSEADDR option, and then closing it) ?
Hmm,
According to strace -o trace.out netstat -at
netstat does this by looking at
/proc/net/tcp
and
/proc/net/tcp6
The used ports are in hex in the second field of the entries in that file.
You can get the state of the connection by looking at the 4th field, for example 0A is LISTEN and 01 is ESTABLISHED.
The holy portable BSD socket API won't allow you to know whether the port is in use before you try to allocate it. Don't try to outsmart the API. I know how tempting it is, I've been in that situation before. But any superficially smart way of doing this (by e.g. the proc filesystem) is prone to subtle errors, compatibility problems in the future, race conditions and so forth.
Grab the source of the netstat command and see how it sees. However, you will always have a race. Also, SO_REUSEADDR won't let you use a port someone else is actively using, of course, just one in close-wait.

Ping servers and check the result from C program?

This is My last question. Now my new requirement is to ping some set of servers and check if they are replying or not. I am trying my way of
system("ping xxx.xx.xx.xx >out.txt");
And then parsing the out.txt for a string "Request timed out.".
This is yielding me good results. But is there any better way to do from c program. Non programmatic ways are also welcome. But mostly I want to go by C program. If the request is timed out I will send a mail through same my way by php. Thanks in advance.
My environment : windows, Tiny C Compiler
A better method for capturing output than system() is to use popen() instead. That way you can capture the output of the command without using a temporary file.
A better method for pinging is to use the Microsoft ICMP API (an introductory page can be found here). This will be possible if your C compiler has the ability to call arbitrary Win32 API functions. In particular, IcmpSendEcho is the function you would want.
Another option is using raw sockets for sending/receiving ICMP packets yourself, or using a library such as libnet for that. You can then take your measurements at a finer granularity. It'll take some time and getting used to, though. :)

Send messages to program through command line

I have this program, we'll call it Host. Host does all kinds of good stuff, but it needs to be able to accept input through the command line while it's running. This means it has to somehow send its other process data and then quit. For example, I need to be able to do this:
./Host --blahblah 3 6 3 5
This should somehow end up calling some function in Host called
handleBlahBlah(int x1, int y1, int x2, int y2){
//do some more sweet stuff
}
Host is a C program, and does not need to support multiple instances.
An example of this is Amarok music player. With Amarok running and playing, you can type "amarok --pause" and it will pause the music.
I need to be able to do this in Linux or Windows. Preferably Linux.
What is the cleanest way to implement this?
If you were on Windows, I'd tell you to use a hidden window to receive the messages, but since you used ./, I assume you want something Unix-based.
In that case, I'd go with a named pipe. Sun has a tutorial about named pipes that might be useful.
The program would probably create the pipe and listen. You could have a separate command-line script which would open the pipe and just echo its command-line arguments to it.
You could modify your program to support the command-line sending instead of using a separate script. You'd do the same basic thing in that case. Your program would look at it's command-line arguments, and if applicable, open the pipe to the "main" instance of the program, and send the arguments through.
If it needs to be cross-platform, you might want to consider making the running instance listen on a TCP port, and have the instance you fire up from the command-line send a message to that port.
I suggest using either a Unix socket or D-Bus. Using a socket might be faster if you're familiar with Unix sockets programming and only want a few operations, whereas D-Bus might make it easier to concentrate on implementing the functionality in a familiar object-oriented way.
Take a look at Beej's Guide to Unix IPC, particularly the chapter on Unix sockets.
What no one has said here is this:
"you can't get there from here".
The command line is only available as it was when your program was invoked.
The example of invoking "fillinthename arguments ..." to communicate with fillinthename once fillinthename is running can only be accomplished by using two instances of the program which communicate with each other.
The other answers suggest ways to achieve the communication.
An amarok like program needs to detect the existence of another instance
of itself in order to know which role it must play, the major role of
persistent message receiver/server, or the minor role of one shot
message sender.
edited to make the word fillinthename actually be displayed.
One technique I have seen is to have your Host program be merely a "shell" for your real program. For example when you launch your application normally (e.g.: ./Host), the program will fork into the "main app" part of your code. When you launch your program in a way that suggests you want to signal the running instance (e.g.: ./Host --send-message restart), the program will fork into the "message sender" part of your code. It's like having two apps in one. Another option that doesn't use fork is to make Host purely a "message sender" app and have your "main app" as a separate executable (e.g.: Host_core) that Host can launch separately.
The "main app" part of your program will need to open up some kind of a communication channel to receive messages, and the "message sender" part will need to connect to that channel and use it to send messages. There are several different options available for sending messages between processes. Some of the more common methods are pipes and sockets. Depending on your OS, you may have additional options available; for instance, QNX has channels and BeOS/Haiku have BMessages. You may also be able to find a library that neatly wraps up this functionality, such as lcm.
So, I may be missing the point here, but by deafult a C program's main function takes two arguments; argc, a count of the number of arguments (at least one), and argv (or arg vector), the argument list. You could just parse through the arguments and call the correct method.
For example:
int main(int argc, *argv[])
{
/*loop through each argument and take action*/
while (--argc > 0)
{
printf(%s%s, *++argv, (argc > 1) ? " " : "");
}
}
would print all of the arguments to screen. I am no C guru, so I hope I haven't made any mistakes.
EDIT: Ok, he was after something else, but it wasn't really clear before the question was edited. Don't have to jump on my rep...

Resources