Serialize Netbios struct to send over TCP/IP in C, possible? - c

I have 2 machines talking to each other using NetBIOS via NetBEUI. I am in the process of replacing NETBEUI with TCP. I am looking for the easiest and fastest way to do it. There is NetBios over TCP/IP protocol available but for some reason it's not working... I could not figure out why. So now, I am thinking to serialize the NetBIOS struct and send it over to another machine using TCP and de-serialize there. The struct look like below. Will serialize approach work?
typedef struct _NCB {
UCHAR ncb_command; /* command code */
UCHAR ncb_retcode; /* return code */
UCHAR ncb_lsn; /* local session number */
UCHAR ncb_num; /* number of our network name */
PUCHAR ncb_buffer; /* address of message buffer */
WORD ncb_length; /* size of message buffer */
UCHAR ncb_callname[NCBNAMSZ]; /* blank-padded name of remote */
UCHAR ncb_name[NCBNAMSZ]; /* our blank-padded netname */
UCHAR ncb_rto; /* rcv timeout/retry count */
UCHAR ncb_sto; /* send timeout/sys timeout */
void (CALLBACK *ncb_post)( struct _NCB * );
UCHAR ncb_lana_num; /* lana (adapter) number */
UCHAR ncb_cmd_cplt; /* 0xff => commmand pending */
#ifdef _WIN64
UCHAR ncb_reserve[18]; /* reserved, used by BIOS */
#else
UCHAR ncb_reserve[10]; /* reserved, used by BIOS */
#endif
HANDLE ncb_event; /* HANDLE to Win32 event which */
/* will be set to the signalled */
/* state when an ASYNCH command */
/* completes */
} NCB, *PNCB;

Related

When implementing traceroute in C , I couldn't find the IP address of the router that send back the timeout error message

In order to receive timeout ICMP message, I set the receive socket recvfd with option IP_RECVERR:
int val=1;
setsockopt(recvfd,IPPROTO_IP,IP_RECVERR,&val,sizeof(int));
And I try to receive the timeout ICMP error message with recvmsg(recvfd,msg,MSG_ERRQUEUE);
The error message is stored in msg, which is a pointer to the struct msghdr.
I look up the manual, 7/ip and recvmsg.
The struct msghdr as follows,
struct iovec { /* Scatter/gather array items */
void *iov_base; /* Starting address */
size_t iov_len; /* Number of bytes to transfer */
};
struct msghdr {
void *msg_name; /* optional address */
socklen_t msg_namelen; /* size of address */
struct iovec *msg_iov; /* scatter/gather array */
size_t msg_iovlen; /* # elements in msg_iov */
void *msg_control; /* ancillary data, see below */
size_t msg_controllen; /* ancillary data buffer len */
int msg_flags; /* flags on received message */
};
The field msg_control points to struct cmsghdr, as follows,
struct cmsghdr {
socklen_t cmsg_len; /* data byte count, including hdr */
int cmsg_level; /* originating protocol */
int cmsg_type; /* protocol-specific type */
/* followed by
unsigned char cmsg_data[]; */
};
and the field cmsg_data points to a struct sock_extended_err, as follows
#define SO_EE_ORIGIN_NONE 0
#define SO_EE_ORIGIN_LOCAL 1
#define SO_EE_ORIGIN_ICMP 2
#define SO_EE_ORIGIN_ICMP6 3
struct sock_extended_err {
uint32_t ee_errno; /* error number */
uint8_t ee_origin; /* where the error originated */
uint8_t ee_type; /* type */
uint8_t ee_code; /* code */
uint8_t ee_pad;
uint32_t ee_info; /* additional information */
uint32_t ee_data; /* other data */
/* More data may follow */
};
struct sockaddr *SO_EE_OFFENDER(struct sock_extended_err *);
In the manual, it says
the macro SO_EE_OFFENDER returns a pointer to the address of the network object where the error originated from given a pointer to the ancillary message.
I tried to convert the struct sock_extended_err into IP address and print it out, but the result is 2.0.0.0 all the time. But I couldn't find elsewhere that stores the IP address of the router that send back the timeout ICMP error message in the above three structs.
Code that receives the error message as follows,
//construct the msghdr struct
struct msghdr* msg=(struct msghdr*)malloc(sizeof(struct msghdr));
char recvBuffer[CMSG_SPACE(64)];
msg->msg_control=recvBuffer;
msg->msg_controllen=sizeof(recvBuffer);
//receive the message
recvmsg(recvfd,msg,MSG_ERRQUEUE);
//visit all the nodes in msg and get the IP address
struct cmsghdr* cmsg=CMSG_FIRSTHDR(msg);
for(;cmsg!=NULL;cmsg=CMSG_NXTHDR(msg,cmsg)){
struct sock_extended_err* exterr=(struct sock_extended_err*)(CMSG_DATA(cmsg));
struct sockaddr* DestAddr=SO_EE_OFFENDER(exterr);
struct sockaddr_in* ad=(struct sockaddr_in*)DestAddr;
char destination[20];
inet_ntop(AF_INET,ad,destination,sizeof(destination));
printf("IP: %20s\n",destination);
}
Could anyone help me ? Thanks.

I can't find DSCP field in IP header, only the deprecated TOS field

I will try to garantee some QoS with my access point made with Raspberry Pi.
Before starting, I'm getting my hands dirty: I read about the tcp, udp and ip headers. In the IP header description I saw the DSCP field, originally defined as the Type of Service field.
DSCP field would provide me interesting infos about the Qos, so I looked for it...but I couldn't find it: I still have the deprecated tos field.
From my /usr/include/netinet/ip.h:
struct ip {
#if __BYTE_ORDER == __LITTLE_ENDIAN
unsigned int ip_hl:4; /* header length */
unsigned int ip_v:4; /* version */
#endif
#if __BYTE_ORDER == __BIG_ENDIAN
unsigned int ip_v:4; /* version */
unsigned int ip_hl:4; /* header length */
#endif
u_int8_t ip_tos; /* type of service */
u_short ip_len; /* total length */
u_short ip_id; /* identification */
u_short ip_off; /* fragment offset field */
#define IP_RF 0x8000 /* reserved fragment flag */
#define IP_DF 0x4000 /* dont fragment flag */
#define IP_MF 0x2000 /* more fragments flag */
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
u_int8_t ip_ttl; /* time to live */
u_int8_t ip_p; /* protocol */
u_short ip_sum; /* checksum */
struct in_addr ip_src, ip_dst; /* source and dest address */
};
Infos about my sistem:
uname -r -> 3.13.0-49-generic
lsb_release -a -> Distributor ID: Ubuntu
Description: Ubuntu 14.04.2 LTS
Release: 14.04
Codename: trusty
The DSCP field has taken the place of the ToS field: these are just two names for the very same field in the IP header. If the sender put a DSCP value into the field, then it's just fine to access it using the ToS field.
Note however that whether and how the DSCP/ToS field will be actually parsed by routers is highly implementation dependent. Most carriers (ISPs) will simply clear the field as it enters their network. Most home routers will ignore the field, although OpenWRT will interpret it as a ToS.
In short — using the DSCP/ToS field without a good understanding of your local network environment is just cargo culting.

Adding attribute to buffer description in PostgreSQL source, now has spinlock error?

I would like to add an attribute to the buffer description in the PostgreSQL source code, but when I try to initialize it I get an error of: PANIC: stuck spinlock (0x7fc1cddd0cd0) detected at freelist.c:206
The struct is described in buf_internals.h as:
typedef struct sbufdesc
{
BufferTag tag; /* ID of page contained in buffer */
BufFlags flags; /* see bit definitions above */
uint16 usage_count; /* usage counter for clock sweep code */
unsigned refcount; /* # of backends holding pins on buffer */
int wait_backend_pid; /* backend PID of pin-count waiter */
int buf_age; //<<<<<<<<<<< The age of the buffer
slock_t buf_hdr_lock; /* protects the above fields */
int buf_id; /* buffer's index number (from 0) */
int freeNext; /* link in freelist chain */
LWLockId io_in_progress_lock; /* to wait for I/O to complete */
LWLockId content_lock; /* to lock access to buffer contents */
} BufferDesc;
but it gets stuck at line 206 of freelist.c, which is just:
LockBufHdr(buf);
All I've added was an int to the struct and set it to zero in the same place all the other buffers are initialized. How could this cause a spinlock error?
It looks like running make clean first has corrected the issue.

MQGET big message ( > 4MB) from the queue results in error 2010

I am trying to receive the message from the queue using ANSI-C and MQGET function. The problem is that I always get error 2010 (MQRC_DATA_LENGTH_ERROR).
I found out that this error concerns parameter 7 of the MQGET call (DataLength). The message on my queue has 7157460 bytes. The channel I am using for MQGET has the "Maximum message length" set to 104857600 (as well as the queue holding the message).
I am even using the MQGET from this example:
http://www.capitalware.biz/dl/code/c/msg2file.zip
And I still end up with error 2010. What am I doing wrong? Should I somehow increase the maximum size of the message in MQSERVER environment variable?
MQGET call:
/* ... */
MQLONG messlen; /* message length received */
MQGET(Hcon, /* connection handle */
Hobj, /* object handle */
&md, /* message descriptor */
&gmo, /* get message options */
buflen, /* pBuffer length */
pBuffer, /* pointer to message buffer */
&messlen, /* message length */
&CompCode, /* completion code */
&Reason); /* reason code */
I've got it! The answer is to use MQCONNX call to connect to queue manager.
Example:
#include <cmqxc.h>
/* ... */
MQCNO mqcno = {MQCNO_DEFAULT} ; /* Connection options */
MQCD mqcd = {MQCD_CLIENT_CONN_DEFAULT}; /* Channel Defs */
/* ... */
mqcd.MaxMsgLength = 104857600L; /* 100 MB */
MQCONNX(mQueueManager.Name,
&mqcno,
&mQueueManager.ConnectionHandle,
&mQueueManager.CompletionCode,
&mQueueManager.ReasonCode);
It worked like a charm!
But please remember - if you find yourself needing to increase the maximum message size - think twice. There is probably something wrong with the design. In another words - MQ should not be used for transferring big messages. MQ File Transfer Edition is one of the solutions then.

How to sniff PPP packet with libpcap?

I can capture packets from eth0 interface, and sniff ip packets as follows
/* IP header */
struct sniff_ip {
u_char ip_vhl; /* version << 4 | header length >> 2 */
u_char ip_tos; /* type of service */
u_short ip_len; /* total length */
u_short ip_id; /* identification */
u_short ip_off; /* fragment offset field */
#define IP_RF 0x8000 /* reserved fragment flag */
#define IP_DF 0x4000 /* dont fragment flag */
#define IP_MF 0x2000 /* more fragments flag */
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
u_char ip_ttl; /* time to live */
u_char ip_p; /* protocol */
u_short ip_sum; /* checksum */
struct in_addr ip_src,ip_dst; /* source and dest address */
};
So if need to capture packets from PPP interface, how to define the header struct?
I just notice that, the length of header is 32 bytes in this case.
If, when you capture on the PPP device with libpcap, the pcap_datalink() routine returns DLT_PPP, then you define the header in the fashion indicated by the entry for LINKTYPE_PPP/DLT_PPP in the tcpdump.org link-layer header types page:
PPP, as per RFC 1661 and RFC 1662; if the first 2 bytes are 0xff and 0x03, it's PPP in HDLC-like framing, with the PPP header following those two bytes, otherwise it's PPP without framing, and the packet begins with the PPP header.

Resources