I am trying to use nl_recvmsgs as a blocking function to receive Netlink messages from a kernel module.
In my example the client sends a message to the kernel and then it calls nl_recvmsgs_report()(is equal to nl_recvmsgs). Then the kernel module sends a return message. That message is successful received by the client.
Now I want the client to listen for more messages in the future and call nl_recvmsgs_report() again. The kernel did not sent any second message. But somehow an ERRORMSG is received by the client. This leads to a SEGFAULT at the client because he tries to parse the message not as an ERRORMSG.
If I check if the message type is 2 , and skip the message parsing, a third call of nl_recvmsgs_report() blocks perfectly fine.
Does someone know why the client receives this ERRORMSG?
Have a look at my github branch. Just call make, sudo insmod nlk.ko, ./nlclient I copied only the relevant parts here.
client code
nlclient.c main() sending and receiving part:
// setup netlink socket
sk = nl_socket_alloc();
nl_socket_disable_seq_check(sk); // disable sequence number check
genl_connect(sk);
int id = genl_ctrl_resolve(sk, DEMO_FAMILY_NAME);
struct nl_msg * msg;
// create a messgae
msg = nlmsg_alloc();
genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, id, 0, // hdrlen
0, // flags
DEMO_CMD, // numeric command identifier
DEMO_VERSION // interface version
);
nla_put_string(msg, DEMO_ATTR1_STRING, "hola");
nla_put_u16(msg, DEMO_ATTR2_UINT16, 0xf1);
// send it
nl_send_auto(sk, msg);
// handle reply
struct nl_cb * cb = NULL;
cb = nl_cb_alloc(NL_CB_CUSTOM);
//nl_cb_set_all(cb, NL_CB_DEBUG, NULL, NULL);
nl_cb_set_all(cb, NL_CB_CUSTOM, cb_handler, &cbarg);
nl_cb_err(cb, NL_CB_DEBUG, NULL, NULL);
int nrecv = nl_recvmsgs_report(sk, cb);
printf("cbarg %d nrecv %d\n", cbarg, nrecv);
printf("First test if it blocks here for incoming messages:\n");
nrecv = nl_recvmsgs_report(sk, cb);
printf("cbarg %d nrecv %d\n", cbarg, nrecv);
printf("Second test if it blocks here for incoming messages:\n");
nrecv = nl_recvmsgs_report(sk, cb);
printf("cbarg %d nrecv %d\n", cbarg, nrecv);
nlclient.c cb_handler() parsing the header and message
struct nlmsghdr * hdr = nlmsg_hdr(msg);
struct genlmsghdr * gnlh = nlmsg_data(hdr);
nl_msg_dump(msg, stderr);
if (hdr->nlmsg_type == 2) {
printf("hdr->nlmsg_type is ERROR. Skipping message parsing!\n");
} else {
int valid =
genlmsg_validate(hdr, 0, DEMO_ATTR_MAX, demo_gnl_policy);
printf("valid %d %s\n", valid, valid ? "ERROR" : "OK");
// one way
struct nlattr * attrs[DEMO_ATTR_MAX + 1];
if (genlmsg_parse(hdr, 0, attrs, DEMO_ATTR_MAX, demo_gnl_policy) < 0)
{
printf("genlsmg_parse ERROR\n");
}
else
{
printf("genlsmg_parse OK\n");
printf("attr1 %s\n", nla_get_string(attrs[DEMO_ATTR1_STRING]));
printf("attr2 %x\n", nla_get_u16(attrs[DEMO_ATTR2_UINT16]));
struct attr_custom * cp = (struct attr_custom *) nla_data(attrs[DEMO_ATTR3_CUSTOM]);
printf("attr3 %d %ld %f %lf\n", cp->a, cp->b, cp->c,cp->d);
}
}
// another way
printf("gnlh->cmd %d\n", gnlh->cmd); //--- DEMO_CMD_ECHO
int remaining = genlmsg_attrlen(gnlh, 0);
struct nlattr * attr = genlmsg_attrdata(gnlh, 0);
while (nla_ok(attr, remaining))
{
printf("remaining %d\n", remaining);
printf("attr # %p\n", attr); // nla_get_string(attr)
attr = nla_next(attr, &remaining);
}
kernel code
nlkernel.c demo_cmd() sending to client part:
/* send message back */
/* allocate some memory, since the size is not yet known use NLMSG_GOODSIZE */
skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
if (skb == NULL) {
goto out;
}
/* create the message */
msg_head =
genlmsg_put(skb, 0, info->snd_seq + 1, &demo_gnl_family, 0,
DEMO_CMD);
if (msg_head == NULL) {
rc = -ENOMEM;
goto out;
}
rc |= nla_put_string(skb, DEMO_ATTR1_STRING,"world");
rc |= nla_put_u16(skb, DEMO_ATTR2_UINT16, 0x1f);
cp.a = 1;
cp.b = 2;
cp.c = 3.0;
cp.d = 4.0;
rc |= nla_put(skb, DEMO_ATTR3_CUSTOM, sizeof(struct attr_custom), &cp);
if (rc != 0) {
goto out;
}
/* finalize the message */
genlmsg_end(skb, msg_head);
/* send the message back */
rc = genlmsg_unicast(&init_net, skb, info->snd_portid);
if (rc != 0) {
goto out;
}
return 0;
output
nlclient console output
./nlclient
-------------------------- BEGIN NETLINK MESSAGE ---------------------------
[NETLINK HEADER] 16 octets
.nlmsg_len = 76
.type = 27 <0x1b>
.flags = 0 <>
.seq = 1458476257
.port = 0
[GENERIC NETLINK HEADER] 4 octets
.cmd = 1
.version = 1
.unused = 0
[PAYLOAD] 56 octets
0a 00 01 00 77 6f 72 6c 64 00 00 00 06 00 02 00 ....world.......
1f 00 00 00 24 00 03 00 01 00 00 00 ff ff ff ff ....$...........
02 00 00 00 00 00 00 00 00 00 40 40 04 88 ff ff ..........##....
00 00 00 00 00 00 10 40 .......#
--------------------------- END NETLINK MESSAGE ---------------------------
valid 0 OK
genlsmg_parse OK
attr1 world
attr2 1f
attr3 1 2 3.000000 4.000000
gnlh->cmd 1
remaining 56
attr # 0x10df344
remaining 44
attr # 0x10df350
remaining 36
attr # 0x10df358
cbarg 123 nrecv 1
First test if it blocks here for incoming messages:
-------------------------- BEGIN NETLINK MESSAGE ---------------------------
[NETLINK HEADER] 16 octets
.nlmsg_len = 36
.type = 2 <ERROR>
.flags = 0 <>
.seq = 1458476256
.port = -1061151077
[ERRORMSG] 20 octets
.error = 0 "Success"
[ORIGINAL MESSAGE] 16 octets
.nlmsg_len = 16
.type = 27 <0x1b>
.flags = 5 <REQUEST,ACK>
.seq = 1458476256
.port = -1061151077
--------------------------- END NETLINK MESSAGE ---------------------------
hdr->nlmsg_type is ERROR. Skipping message parsing!
gnlh->cmd 0
cbarg 123 nrecv 1
Second test if it blocks here for incoming messages:
KERNEL syslog
kernel: [ 4694.318428] got demo_cmd
kernel: [ 4694.318430] attr1: hola
kernel: [ 4694.318431] attr2: f1
Sorry for taking so long.
The output is somewhat misleading. That's not an error message; it's an automatic ACK. Netlink defines ACKs to be "error" messages with error code 0.
(Zero is typical jargon for success in the C language.)
Since you're crafting an answer, you probably don't need ACKs anyway. You can stop your client from requesting ACKs by adding a call to nl_socket_disable_auto_ack().
I'd hack it close to sequence check disabling because it's kind of similar:
sk = nl_socket_alloc();
nl_socket_disable_seq_check(sk);
nl_socket_disable_auto_ack(sk);
genl_connect(sk);
Related
I keep receiving fragment udp packets and do reassemble two fragment packets to one, it become multi-seg packet, and then send to another NIC,
(NIC 710 port0 -> do reassembel -> NIC 710 port1 -> NIC 710 port1 recevice packets -> do fragment -> NIC 710 port0)
I receive a strange packet which only have one segment, but m-> next is not NULL.
so after pkt_len minus two times, pkt_len become underflow,
this problem run about 5.5hours ocuur, how to prevent this problem?
platform:
OS: Ubuntu 18.04
kernel version: Linux mec 4.15.0-112-generic
DPDK version: DPDK 19.11.11 (LTS)
NIC: Intel 710
NIC firmware:
mec#mec:~$ sudo lshw -c Network | grep X710 -B10
*-network:0 DISABLED
description: Ethernet interface
product: Ethernet Controller X710 for 10GbE SFP+
--
version: 02
serial: f8:f2:1e:58:9b:b0
size: 10Gbit/s
width: 64 bits
clock: 33MHz
capabilities: pm msi msix pciexpress vpd bus_master cap_list rom ethernet physical fibre autonegotiation
configuration: autonegotiation=off broadcast=yes driver=i40e driverversion=2.1.14-k duplex=full firmware=6.80 0x80003d73 18.8.9 latency=0 link=no multicast=yes port=fibre speed=10Gbit/s
resources: irq:97 memory:93000000-93ffffff memory:94018000-9401ffff memory:94100000-9417ffff
*-network:1 DISABLED
description: Ethernet interface
product: Ethernet Controller X710 for 10GbE SFP+
--
version: 02
serial: f8:f2:1e:58:9b:b1
size: 10Gbit/s
width: 64 bits
clock: 33MHz
capabilities: pm msi msix pciexpress vpd bus_master cap_list rom ethernet physical fibre autonegotiation
configuration: autonegotiation=off broadcast=yes driver=i40e driverversion=2.1.14-k duplex=full firmware=6.80 0x80003d73 18.8.9 latency=0 link=no multicast=yes port=fibre speed=10Gbit/s
resources: irq:97 memory:92000000-92ffffff memory:94010000-94017fff memory:94180000-941fffff
*-network:2 DISABLED
description: Ethernet interface
product: Ethernet Controller X710 for 10GbE SFP+
--
version: 02
serial: f8:f2:1e:58:9b:b2
size: 10Gbit/s
width: 64 bits
clock: 33MHz
capabilities: pm msi msix pciexpress vpd bus_master cap_list rom ethernet physical fibre autonegotiation
configuration: autonegotiation=off broadcast=yes driver=i40e driverversion=2.1.14-k duplex=full firmware=6.80 0x80003d73 18.8.9 latency=0 link=no multicast=yes port=fibre speed=10Gbit/s
resources: irq:97 memory:91000000-91ffffff memory:94008000-9400ffff memory:94200000-9427ffff
*-network:3 DISABLED
description: Ethernet interface
product: Ethernet Controller X710 for 10GbE SFP+
mec#mec:~$ sudo ethtool -i enp3s0f0
driver: i40e
version: 2.1.14-k
firmware-version: 6.80 0x80003d73 18.8.9
expansion-rom-version:
bus-info: 0000:03:00.0
supports-statistics: yes
supports-test: yes
supports-eeprom-access: yes
supports-register-dump: yes
supports-priv-flags: yes
int rte_mbuf_check_handmade1(const struct rte_mbuf *m, int is_header,
const char **reason)
{
unsigned int nb_segs, pkt_len;
if (m == NULL) {
*reason = "mbuf is NULL";
return -1;
}
/* generic checks */
if (m->pool == NULL) {
*reason = "bad mbuf pool";
return -1;
}
if (m->buf_iova == 0) {
*reason = "bad IO addr";
return -1;
}
if (m->buf_addr == NULL) {
*reason = "bad virt addr";
return -1;
}
uint16_t cnt = rte_mbuf_refcnt_read(m);
if ((cnt == 0) || (cnt == UINT16_MAX)) {
*reason = "bad ref cnt";
return -1;
}
/* nothing to check for sub-segments */
if (is_header == 0)
return 0;
/* data_len is supposed to be not more than pkt_len */
if (m->data_len > m->pkt_len) {
*reason = "bad data_len";
return -1;
}
nb_segs = m->nb_segs;
pkt_len = m->pkt_len;
uint16_t port = m->port, data_len = m->data_len, ori_nb_segs = m->nb_segs, buf_len = m->buf_len;
uint32_t ori_pkt_len = m->pkt_len;
uint64_t ol_flags = m->ol_flags;
struct rte_mbuf* last_ptr;
// os_printf("before loop: ol_flags = %"PRIu64", port = %"PRIu16", data_len = %"PRIu16", pkt_len = %"PRIu32", nb_segs = %"PRIu16", buf_len = %"PRIu16"\n", m->ol_flags, m->port, m->data_len, m->pkt_len, m->nb_segs, m->buf_len);
do {
if (m->data_off > m->buf_len) {
*reason = "data offset too big in mbuf segment";
return -1;
}
if (m->data_off + m->data_len > m->buf_len) {
*reason = "data length too big in mbuf segment";
return -1;
}
os_log_debug("bf loop: ol_flags = %"PRIu64", port = %"PRIu16", data_len = %"PRIu16", pkt_len = %"PRIu32", nb_segs = %"PRIu16", buf_len = %"PRIu16"\n", m->ol_flags, m->port, m->data_len, m->pkt_len, m->nb_segs, m->buf_len);
nb_segs -= 1;
pkt_len -= m->data_len;
os_log_debug("in loop: ol_flags = %"PRIu64", port = %"PRIu16", data_len = %"PRIu16", pkt_len = %"PRIu32", nb_segs = %"PRIu16", buf_len = %"PRIu16"\n", m->ol_flags, m->port, m->data_len, pkt_len, nb_segs, m->buf_len);
last_ptr = (struct rte_mbuf* )m;
} while ((m = m->next) != NULL);
if(pkt_len){
os_printf("before loop: ol_flags = %"PRIu64", port = %"PRIu16", data_len = %"PRIu16", pkt_len = %"PRIu32", nb_segs = %"PRIu16", buf_len = %"PRIu16"\n", ol_flags, port, data_len, ori_pkt_len, ori_nb_segs, buf_len);
os_printf("after loop: pkt_len = %"PRIu32", nb_segs = %"PRIu16"\n", pkt_len, nb_segs);
if(last_ptr != NULL){
os_printf("last_ptr is not NULL and addr = %p\n", last_ptr);
} else {
os_printf("last_ptr is NULL\n");
}
}
if (nb_segs) {
*reason = "bad nb_segs";
return -1;
}
if (pkt_len) {
*reason = "bad pkt_len";
return -1;
}
return 0;
}
void
rte_mbuf_sanity_check_handmade1(const struct rte_mbuf *m, int is_header)
{
const char *reason;
if (rte_mbuf_check_handmade1(m, is_header, &reason)){
FILE* f = fopen("dumplog_sanity.txt", "w");
rte_pktmbuf_dump(f, m, rte_pktmbuf_pkt_len(m));
rte_pktmbuf_dump(stdout, m, rte_pktmbuf_pkt_len(m));
fclose(f);
rte_panic("%s\n", reason);
}
}
static inline char *rte_pktmbuf_adj_handmade(struct rte_mbuf *m, uint16_t len)
{
rte_mbuf_sanity_check_handmade1(m, 1);
uint16_t diff_of_len_data_len = len - m->data_len;
if (unlikely(len > m->data_len)){
os_printf("rte_pktmbuf_adj_handmade: get strange pkt!\n");
os_printf("len = %"PRIu16", m->data_len = %"PRIu16"\n", len, m->data_len);
os_printf("m->pkt_len = %"PRIu16", m-> data_off = %"PRIu16"\n", m->pkt_len, m->data_off);
return NULL;
}
/* NB: elaborating the addition like this instead of using
* += allows us to ensure the result type is uint16_t
* avoiding compiler warnings on gcc 8.1 at least */
uint16_t datalen,dataoff,pktlen;
datalen = (uint16_t)(m->data_len - len);
dataoff = (uint16_t)(m->data_off + len);
pktlen = (m->pkt_len - len);
if(0)
printf("%"PRIu16"%"PRIu16"%"PRIu16"%"PRIu16"",datalen,dataoff,pktlen,diff_of_len_data_len);
m->data_len = (uint16_t)(m->data_len - len);
m->data_off = (uint16_t)(m->data_off + len);
m->pkt_len = (m->pkt_len - len);
return (char *)m->buf_addr + m->data_off;
}
here is log
Jul 19 23:22:04 mec cht_mec_dp[3607]: bf loop: ol_flags = 449, port = 0, data_len = 70, pkt_len = 70, nb_segs = 1, buf_len = 2176
Jul 19 23:22:04 mec cht_mec_dp[3607]: in loop: ol_flags = 449, port = 0, data_len = 70, pkt_len = 0, nb_segs = 0, buf_len = 2176
Jul 19 23:22:04 mec cht_mec_dp[3607]: bf loop: ol_flags = 449, port = 0, data_len = 32, pkt_len = 32, nb_segs = 1, buf_len = 2176
Jul 19 23:22:04 mec cht_mec_dp[3607]: in loop: ol_flags = 449, port = 0, data_len = 32, pkt_len = 4294967264, nb_segs = 4294967295, buf_len = 2176
Jul 19 23:22:04 mec cht_mec_dp[3607]: before loop: ol_flags = 449, port = 0, data_len = 70, pkt_len = 70, nb_segs = 1, buf_len = 2176
Jul 19 23:22:04 mec cht_mec_dp[3607]: after loop: pkt_len = 4294967264, nb_segs = 4294967295
Jul 19 23:22:04 mec cht_mec_dp[3607]: last_ptr is not NULL and addr = 0x16dfb3300
Jul 19 23:22:04 mec cht_mec_dp[3607]: PANIC in rte_mbuf_sanity_check():
Jul 19 23:22:04 mec cht_mec_dp[3607]: bad nb_segs
here is my dump
dump mbuf at 0x16e49c9c0, iova=1fae49ca40, buf_len=2176
pkt_len=70, ol_flags=180, nb_segs=1, in_port=0
segment at 0x16e49c9c0, data=0x16e49cac0, data_len=70
Dump data at [0x16e49cac0], len=70
00000000: 34 17 EB 10 37 82 E4 43 4B 79 8C 20 81 00 01 2E | 4...7..CKy. ....
00000010: 08 00 45 00 00 34 B5 22 00 B9 40 11 47 43 0A 1E | ..E..4."..#.GC..
00000020: 04 5B 0A 1E 65 04 00 00 00 00 00 00 00 00 00 00 | .[..e...........
00000030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................
00000040: 00 00 00 00 00 00 | ......
dump mbuf at 0x16e4a38c0, iova=1fae4a3940, buf_len=2176
pkt_len=32, ol_flags=1c1, nb_segs=1, in_port=0
segment at 0x16e4a38c0, data=0x16e4a39e6, data_len=32
Dump data at [0x16e4a39e6], len=32
00000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................
00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................
I have verified in wireshark that my TCP handshake SYN+ACK packet after receiving SYN packet is getting ignored
This is wireshark main view that shows within time wireshark read my SYN+ACK packet for RTT. but my linux socket api function connect acting dummy and send SYN again, Wht I need to do in this case I am attaching my wireshark packet times plus actual communication packets, I need someone with knowledge of this and C to answer this very much thanks
This is recorded time in wireshark when packets in attempted handshake are read
This is received packet in my program code
SYN
0000 45 00 00 3c fa ed 40 00 40 06 aa 5a c0 a8 0a 14
0010 c0 a8 0a 0f bc be 00 50 f8 08 9d 5b 00 00 00 00
0020 a0 02 fa f0 bb 0f 00 00 02 04 05 b4 04 02 08 0a
0030 9a 68 0f b0 00 00 00 00 01 03 03 07
ACK SYN with valid checksums, sequence number and acknowledgement number
0000 45 00 00 28 00 64 40 00 40 06 a4 f8 c0 a8 0a 0f
0010 c0 a8 0a 14 00 50 bc be 00 00 00 03 f8 08 9d 5c
0020 50 12 fa f0 cc f6 00 00
And this is my linux connect function complete dummy behavior by sending SYN again
0000 45 00 00 3c fa ee 40 00 40 06 aa 59 c0 a8 0a 14
0010 c0 a8 0a 0f bc be 00 50 f8 08 9d 5b 00 00 00 00
0020 a0 02 fa f0 b7 1b 00 00 02 04 05 b4 04 02 08 0a
0030 9a 68 13 a4 00 00 00 00 01 03 03 07
Can anyone please tell me how to handle this, since I am clueless on this, Is there any command that I can use to make my connect function TCP Handshake handling more attentive to my SYN+ACK packet and finally done with responding only ACK instead of playing plain stupid to send SYN again
As #LuisColorado mentioned to ask how am I generating the packet so the answer is this is how
this is my receiver thread that also transmit response TCP packets like SYN+ACK
void * receiver(void *data)
{
//struct sockaddr_in cliaddr = {0};
int recvlen = -1;
int writelen = -1;
//socklen_t clilen = sizeof(cliaddr);
while (!_do_exit)
{
//recvlen = rrecvfrom(_udp_fd, buf, sizeof(buf), 0, (struct sockaddr*)&cliaddr, &clilen);
char buf[VPN_MAX_MTU] = {0};
char buf_1[VPN_MAX_MTU] = {0};
memset(buf,0,VPN_MAX_MTU);
memset(buf_1,0,VPN_MAX_MTU);
memset(buf,0,VPN_MAX_MTU);
memset(buf_1,0,VPN_MAX_MTU);
char *str_source=malloc(18);
char *str_dest=malloc(18);
memset(str_source,0,18);
memset(str_dest,0,18);
recvlen=read(_tun_fd,buf,VPN_MAX_MTU);
if(recvlen>0)
{
//BUFFER received here
struct iphdr *iph=(struct iphdr *)buf;
struct iphdr *ip=(struct iphdr *)buf_1;
int y=0;
for(int b=0;b<(sizeof(struct iphdr)+sizeof(struct tcphdr));b++)
{
if(y==20)
{
y=0;
//printf("\n");
}
//printf("%x ",buf[b]<<24);
y++;
}
// tcph->check=(tcp_chksum(iph,tcph));
//iph->check = csum(iph, sizeof(*iph));
char str_src[18]={0};
char str_dest_t[18]={0};
//printf("IN %s %s\n",get_ip_str_1(iph->saddr,str_src),get_ip_str_1(iph->daddr,str_dest_t));
memcpy(&ip->daddr,&iph->saddr,sizeof(uint32_t));
memcpy(&ip->saddr,&iph->daddr,sizeof(uint32_t));
//printf("OUT %s %s\n",get_ip_str_1(ip->saddr,str_src),get_ip_str_1(ip->daddr,str_dest_t));
//Create ip
//DOUBLE CHECK FOR BYTE ORDER
//ip->tot_len=iph->tot_len;
populate_ip_some(iph,ip);
ip->tos=0;
ip->tos=iph->tos;
ip->ihl = 5;
ip->version = 4;
ip->tot_len = htons(sizeof(struct iphdr) + sizeof(struct tcphdr));
ip->protocol = 6;
ip->check=0;
//DOUBLE CHECK FOR BYTE ORDER
ip->id=htons(100);
ip->check = htons(csum(ip, sizeof(*ip)));
//printf("before %d \n",htons(iph->check));
iph->check=0;
//printf("middle %d\n",iph->check);
//DOUBLE CHECK FOR BYTE ORDER
iph->check = htons(csum(iph, sizeof(*iph)));
int i=iph->ihl*4;
struct tcphdr *tcph=(struct tcphdr *)(buf+i);
//printf("tcp before %x\n",htons(tcph->check));
tcph->check=0;
printf("TCP START\n");
tcph->check=(tcp_chksum(iph,tcph));
printf("TCP END\n");
//printf("tcp after %d\n",(tcph->check));
//printf("i == %d\n",i);
//POSSIBLY PRINT IPH for fun
//for(int a=0;a<recvlen;a++)
//printf("%x\n",buf[a]);
//GET ihl SEND -- tcp
int j=(ip->ihl*4);
//printf("j == %d\n",j);
int x=0;
//SEEK filling
struct tcphdr *tcp=(struct tcphdr *)(buf_1+20);
//populate_tcp_some(tcph,tcp);//Do LOOK AT THIS FUNCTION TO [SEE/CORRECT IT] >:)
if(tcph->syn==1)
{
printf("WHAT THE HELL THEN WHY\n");
printf("syn\n");
populate_tcp_some(tcph,tcp);
tcp->seq=htonl(1);
// tcp->ack_seq=1;
tcp->syn=1;
tcp->ack=1;
tcp->res1=0;
tcp->res1=0;
tcp->urg=0;
tcp->psh=0;
tcp->fin=0;
tcp->doff=5;
tcp->source=htons(80);
int xx=ntohl(tcph->seq)+1;
printf("\n\nfwdfwdfwd FAWAD %x\n\n",xx);
tcp->ack_seq=htonl(xx);
// printf("received tcp syn = %d\n",tcph->syn);
}
else
{
populate_tcp_some(tcph,tcp);
tcp->syn=0;
tcp->ack=1;
tcp->seq=htonl(1);
tcp->res1=0;
tcp->res1=0;
tcp->urg=0;
tcp->psh=0;
tcp->fin=0;
tcp->doff=5;
tcp->ack_seq=htonl(ntohs(tcph->seq)+1);
// printf("sending tcp syn = %d ack = %d\n",tcp->syn,tcp->ack);
}
printf("syn=%d | ack = %d | fin = %d | %d seq = %d ack_seq = %d | urg = %d | doff = %d | psh = %d rst = %d | rst2 = %d\n",tcp->syn,tcp->ack,tcp->fin,tcp->seq,tcp->ack_seq,tcp->urg,tcp->doff,tcp->psh,tcp->res1,tcp->res2);
//populate_tcp_some(tcph,tcp);
tcp->dest=tcph->source;
tcp->window=htons(40);//tcph->window;
//tcp->ack_seq=tcph->seq;
//printf("%d %d SOURCE PORT \n",ntohs(tcph->source),ntohs(tcp->dest));
tcp->source=htons(80);
printf("%d %d PORTS \n",ntohs(tcp->source),ntohs(tcp->dest));
tcp->check=0;
//TCP CHECKSUM ABOUT TRIPPLE WOW
tcp->check=htons(tcp_chksum(ip,tcp));
//printf("tcpH = %d | tcp = %d\n",tcph->check,htons(tcp->check));
//IF needed make payload data
//WRITE
if (recvlen > 0)
{
writelen = write(_tun_fd, buf_1, sizeof(struct iphdr)+sizeof(struct tcphdr));
//debug("SR:%04d\n", recvlen);
//debug("TW:%04d\n", writelen);
if (writelen < 0)
{
//debug("%s: rwrite() %s [%d]\n", _progname, strerror(errno), errno);
//break;//NO NEED
}
}
else if (recvlen < 0)
{
//debug("%s: rrecvfrom() %s\n", _progname, strerror(errno));
//break;//NO NEED
}
else if (recvlen == 0)
{
//why
}
//FINALLY THEN SEND || DO WIRE SHARK
}
// ...:)__ :) __:) ___:)___ (: __(:__ (;...
}
debug("** Receiver ending.\n");
pthread_exit(NULL);
}
I try to create a module for encrypt network packets but when try get data from sk_buff and print it in Hexa not get a correct packet.
I use this method to print data in Hexa :
void pkt_hex_dump(struct sk_buff *skb)
{
size_t len;
int rowsize = 16;
int i, l, linelen, remaining;
int li = 0;
uint8_t *data, ch;
printk("Packet hex dump:\n");
data = (uint8_t *) skb_mac_header(skb);
if (skb_is_nonlinear(skb)) {
len = skb->data_len;
} else {
len = skb->len;
}
remaining = len;
for (i = 0; i < len; i += rowsize) {
printk("%06d\t", li);
linelen = min(remaining, rowsize);
remaining -= rowsize;
for (l = 0; l < linelen; l++) {
ch = data[l];
//data[l] = '1';
printk(KERN_CONT "%02X ", (uint32_t) ch);
}
data += linelen;
li += 10;
printk(KERN_CONT "\n");
}
}
I used this sample to create a chat application.
And output when I send hello world message from client to server is :
[ 3981.963124] Packet hex dump:
[ 3981.963125] 000000 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00
[ 3981.963128] 000010 00 34 6A 1F 40 00 40 06 D1 A2 7F 00 01 01 7F 00
[ 3981.963130] 000020 00 01 07 E4 BD 36 A2 52 E9 62 6D 40 3D FE 80 10
[ 3981.963133] 000030 02 00 FF 28
And I try to follow this solution but can't get any output.
My hook function
static unsigned int hfunc( void *priv, struct sk_buff *skb, const struct nf_hook_state *state){
struct iphdr *iph; /* IPv4 header */
struct tcphdr *tcph; /* TCP header */
uint16_t sport;
uint16_t dport;
struct ethhdr *ether = eth_hdr(skb);
iph = ip_hdr(skb); /* get IP header */
tcph = tcp_hdr(skb); /* get TCP header */
sport = ntohs(tcph->source);
dport = ntohs(tcph->dest);
/* Watch only port of interest */
if (dport == PTCP_WATCH_PORT || sport == PTCP_WATCH_PORT){
printk(KERN_INFO "UDP packet is received: {'sport': %d; 'dport': %d}\n", sport, dport);
printk("Source: %x:%x:%x:%x:%x:%x\n", ether->h_source[0], ether->h_source[1], ether->h_source[2], ether->h_source[3], ether->h_source[4], ether->h_source[5]);
printk("Destination: %x:%x:%x:%x:%x:%x\n", ether->h_dest[0], ether->h_dest[1], ether->h_dest[2], ether->h_dest[3], ether->h_dest[4], ether->h_dest[5]);
printk("Protocol: %d\n", ether->h_proto);
pkt_hex_dump(skb);
}
return NF_ACCEPT;
}
I have been using Cooja in Instant Contiki v2.7. I have added the global and pcap header in the write_to_serial() function in tunslip6.c . Later these packets are sent to the named pipe /tmp/myfifo (which will be the interface for wireshark). And then to display it in wireshark. But when the wireshark is opened (wireshark -k -i /tmp/myfifo), it gives the prompt " Frame 1 too long (-16711680 bytes) "
Below is the code snippet of write_to_serial().
if(verbose>2) {
if (timestamp) stamptime();
printf("Packet from TUN of length %d - write SLIP\n", len);
if (verbose>4) {
#if WIRESHARK_IMPORT_FORMAT
printf("0000");
for(i = 0; i < len; i++) {
printf(" %02x",p[i]);
}
mkfifo(myfifo,0777);
fd=open(myfifo,O_WRONLY);
//add global header only once and packet header
if(gb==0) //gb globally declared ; int gb=0
{
header.magic = 0xa1b2c3d4;
header.version_major = 2;
header.version_minor = 4;
header.thiszone =0;
header.sigfigs = 0;
header.snaplen = 65535;
header.linktype = 113;
bufg[0]=header.magic ;
bufg[1]=header.version_major ;
bufg[2]=header.version_minor ;
bufg[3]=header.thiszone ;
bufg[4]=header.sigfigs ;
bufg[5]=header.snaplen ;
bufg[6]=header.linktype;
// pcap packet header
gettimeofday(&time,0);
pcap_header.ts.tv_sec = time.tv_sec;
pcap_header.ts.tv_usec = time.tv_usec;
pcap_header.caplen = len;
pcap_header.len = len;
bufp[0]=pcap_header.ts.tv_sec ;
bufp[1]=pcap_header.ts.tv_usec ;
bufp[2]=pcap_header.caplen ;
bufp[3]=pcap_header.len ;
if (((write(fd,bufg,7))&&(write(fd,bufp,4))&&(write(fd,p,len)))< 0)
fputs("write() of bytes failed!\n", stderr);
else
printf("\nSuccessfully wrote bytes ");
gb++;
}
else if(gb>0)
{
gettimeofday(&time,0);
pcap_header.ts.tv_sec = time.tv_sec;
pcap_header.ts.tv_usec = time.tv_usec;
pcap_header.caplen = len;
pcap_header.len = len;
bufp[0]=pcap_header.ts.tv_sec ;
bufp[1]=pcap_header.ts.tv_usec ;
bufp[2]=pcap_header.caplen ;
bufp[3]=pcap_header.len ;
if (((write(fd,bufp,4))&&(write(fd,p,len)))< 0)
fputs("write() of bytes failed!\n", stderr);
else
printf("Successfully wrote bytes\n");
}
#endif
The value printed by the pointer p is
Packet from TUN of length 48 - write SLIP
0000 60 00 00 00 00 08 3a ff fe 80 00 00 00 00 00 00 00 00 00 00 00 00 00 01 ff 02 00 00 00 00 00 00 00 00 00 00 00 00 00 02 85 00 7d 36 00 00 00 00
And the fifo is dumped with the values:
0000000 a1b2c3d4 92000002 60567aeb 00000000
0000020 feff3a08 00000080 00000000 00000000
0000040 ff010000 00000002 00000000 00000000
0000060 85020000 00367d00 93000000 60567aeb
0000100 00000000 feff3a08 00000080 00000000
0000120 00000000 ff010000 00000002 00000000
0000140 00000000 85020000 00367d00 97000000
0000160 60567aeb 00000000 feff3a08 00000080
0000200 00000000 00000000 ff010000 00000002
0000220 00000000 00000000 85020000 00367d00
What should be done inorder to rectify this error?
Based on the binary dump, "a1b2c3d4" means that it's big endianness. But the frame length of ff010000 doesn't make sense. I guess you meant to use little endianess, which starts with "d4c3b2a1". Good luck.
It is because the values assigned are in the array which was previously declared as unsigned long. The exact values got changed when this was done. Instead, I wrote the values directly from the structure to the pipe and also added the ethernet header between the pcap header and the ip header.
This is how it looks after editing the code
fd=open(myfifo,O_WRONLY);
if (fd == -1)
{
// Could not open the port.
perror(" Unable to open named pipe");
}
else
printf("\nPipe open : Successsful\n");
eth.h_dest[ETH_ALEN]=(unsigned char){0x00 ,0x00 ,0x00 ,0x00,0x00 ,0x00};
eth.h_source[ETH_ALEN]=(unsigned char){0x00 ,0x00 ,0x00 ,0x00,0x00 ,0x00};
eth.h_proto=0xDD86;
//add global header only once and packet header
if(gb==0)
{
header.magic = 0xa1b2c3d4;
header.version_major = 2;
header.version_minor = 4;
header.thiszone =0;
header.sigfigs = 0;
header.snaplen = 65535;
header.linktype = 1;
// pcap packet header
gettimeofday(&time,0);
pcap_header.ts.tv_sec = time.tv_sec;
pcap_header.ts.tv_usec = time.tv_usec;
pcap_header.caplen = len;
pcap_header.len = len;
if (write(fd,&header,sizeof(header))< 0)
fputs("write() of bytes failed!\n", stderr);
else
printf("\nSuccessfully wrote global_header ");
if (write(fd,&pcap_header,sizeof(pcap_header))< 0)
fputs("write() of bytes failed!\n", stderr);
else
printf("\nSuccessfully wrote pcap header");
if (write(fd,ð,14)< 0)
fputs("write() of eth bytes failed!\n", stderr);
else
printf("\nSuccessfully wrote ethernet header ");
if (write(fd,p,len)< 0)
fputs("write() of ip bytes failed!\n", stderr);
else
printf("\nSuccessfully wrote ipheader\n ");
gb++;
}
else if(gb>0)
{
gettimeofday(&time,0);
pcap_header.ts.tv_sec = time.tv_sec;
pcap_header.ts.tv_usec = time.tv_usec;
pcap_header.caplen = len;
pcap_header.len = len;
if (write(fd,&pcap_header,sizeof(pcap_header))< 0)
fputs("write() of bytes failed!\n", stderr);
else
printf("\nSuccessfully wrote pcap header");
if (write(fd,ð,14)< 0)
fputs("write() of eth bytes failed!\n", stderr);
else
printf("\nSuccessfully wrote ethernet header ");
if (write(fd,p,len)< 0)
fputs("write() of ip bytes failed!\n", stderr);
else
printf("\nSuccessfully wrote ipheader\n ");}
And later the packets sent to the pipe is:
0000000 a1b2c3d4 00040002 00000000 00000000
0000020 0000ffff 00000001 56808fb9 000ed0b2
0000040 00000030 00000030 41880000 3600bf8e
0000060 4188b77c 0060dd86 08000000 80feff3a
0000100 00000000 00000000 00000000 02ff0100
0000120 00000000 00000000 00000000 00850200
0000140 0000367d 8fbd0000 ad725680 0030000e
0000160 00300000 00000000 bf8e4188 b77c3600
0000200 dd864188 00000060 ff3a0800 000080fe
0000220 00000000 00000000 01000000 000002ff
0000240 00000000 00000000 02000000 367d0085
0000260 00000000 56808fc1 000eccfe 00000030
0000300 00000030 41880000 3600bf8e 4188b77c
0000320 0060dd86 08000000 80feff3a 00000000
0000340 00000000 00000000 02ff0100 00000000
0000360 00000000 00000000 00850200 0000367d
I have some code that captures audio using the PortAudio library, and then tries to package it into the WAV codec. I then attempt to convert that file to a FLAC file codec, but it keeps telling me it's not a valid .wav file.
wav.h:
#include <stdint.h>
#include <string.h>
/**
* #struct WaveHeader
* #brief A basic WAVE header
*/
typedef struct
{
char RIFF_marker[4];
uint32_t file_size;
char filetype_header[4];
char format_marker[4];
uint32_t data_header_length;
uint16_t format_type;
uint16_t number_of_channels;
uint32_t sample_rate;
uint32_t bytes_per_second;
uint16_t bytes_per_frame;
uint16_t bits_per_sample;
} WaveHeader;
WaveHeader *genericWAVHeader(uint32_t sample_rate, uint16_t bit_depth, uint16_t channels);
WaveHeader *retrieveWAVHeader(const void *ptr);
int writeWAVHeader(FILE* fd, WaveHeader *hdr);
int recordWAV(const char *fileName, WaveHeader *hdr, uint32_t duration);
capture.c:
#include <stdio.h>
#include <stdlib.h>
#include <portaudio.h>
#include <unistd.h>
#include <math.h>
#include "wav.h"
typedef struct
{
int frameIndex; /* Index into sample array. */
int maxFrameIndex;
char* recordedSamples;
} PAData;
WaveHeader *genericWAVHeader(uint32_t sample_rate, uint16_t bit_depth, uint16_t channels)
{
WaveHeader *hdr = malloc(sizeof(*hdr));
if (!hdr) return NULL;
memcpy(&hdr->RIFF_marker, "RIFF", 4);
memcpy(&hdr->filetype_header, "WAVE", 4);
memcpy(&hdr->format_marker, "fmt ", 4);
hdr->data_header_length = 16;
hdr->format_type = 1;
hdr->number_of_channels = channels;
hdr->sample_rate = sample_rate;
hdr->bytes_per_second = sample_rate * channels * bit_depth / 8;
hdr->bytes_per_frame = channels * bit_depth / 8;
hdr->bits_per_sample = bit_depth;
return hdr;
}
int writeWAVHeader(FILE* fd, WaveHeader *hdr)
{
if (!hdr) return -1;
fwrite(&hdr->RIFF_marker, sizeof(*hdr->RIFF_marker), sizeof(&hdr->RIFF_marker), fd);
fwrite(&hdr->file_size, sizeof(hdr->file_size), sizeof(&hdr->file_size), fd);
fwrite(&hdr->filetype_header, sizeof(*hdr->filetype_header), sizeof(&hdr->filetype_header), fd);
fwrite(&hdr->format_marker, sizeof(*hdr->format_marker), sizeof(&hdr->format_marker), fd);
fwrite(&hdr->data_header_length, sizeof(hdr->data_header_length), sizeof(&hdr->data_header_length), fd);
fwrite(&hdr->format_type, sizeof(hdr->format_type), sizeof(&hdr->format_type), fd);
fwrite(&hdr->number_of_channels, sizeof(hdr->number_of_channels), sizeof(&hdr->number_of_channels), fd);
fwrite(&hdr->sample_rate, sizeof(hdr->sample_rate), sizeof(&hdr->sample_rate), fd);
fwrite(&hdr->bytes_per_second, sizeof(hdr->bytes_per_second), sizeof(&hdr->bytes_per_second), fd);
fwrite(&hdr->bytes_per_frame, sizeof(hdr->bytes_per_frame), sizeof(&hdr->bytes_per_frame), fd);
fwrite(&hdr->bits_per_sample, sizeof(hdr->bits_per_sample), sizeof(&hdr->bits_per_sample), fd);
fwrite("data", 1, sizeof("data") - 1, fd);
uint32_t data_size = hdr->file_size - 36;
fwrite(&data_size, sizeof(data_size), sizeof(&data_size), fd);
return 0;
}
static int recordCallback(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags, void *userData)
{
PAData *data = (PAData*) userData;
const char *rptr = (const char*) inputBuffer;
char *wptr = &data->recordedSamples[data->frameIndex * 2 /*channels*/];
long framesToCalc;
int finished;
unsigned long framesLeft = data->maxFrameIndex - data->frameIndex;
(void) outputBuffer; /* Prevent unused variable warnings. */
(void) timeInfo;
(void) statusFlags;
(void) userData;
if(framesLeft < framesPerBuffer)
{
framesToCalc = framesLeft;
finished = paComplete;
}
else
{
framesToCalc = framesPerBuffer;
finished = paContinue;
}
if(!inputBuffer)
{
for(long i = 0; i < framesToCalc; i++)
{
*wptr++ = 0; /* left */
*wptr++ = 0; /* right */
}
}
else
{
for(long i = 0; i < framesToCalc; i++)
{
*wptr++ = *rptr++; /* left */
*wptr++ = *rptr++; /* right */
}
}
data->frameIndex += framesToCalc;
return finished;
}
int recordWAV(const char *fileName, WaveHeader *hdr, uint32_t duration)
{
PaStreamParameters inputParameters;
PaStream* stream;
PaError err = paNoError;
PAData data;
int totalFrames;
int numSamples;
int numBytes;
char max, val;
double average;
printf("%d", hdr->bytes_per_second);
data.maxFrameIndex = totalFrames = duration * hdr->sample_rate; /* Record for a few seconds. */
data.frameIndex = 0;
numSamples = totalFrames * hdr->number_of_channels;
numBytes = numSamples;
data.recordedSamples = malloc(numBytes);
if(!data.recordedSamples)
{
printf("Could not allocate record array.\n");
goto done;
}
for(int i = 0; i < numSamples; i++) data.recordedSamples[i] = 0;
if((err = Pa_Initialize())) goto done;
inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
if (inputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default input device.\n");
goto done;
}
inputParameters.channelCount = 2; /* stereo input */
inputParameters.sampleFormat = 1;
inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
inputParameters.hostApiSpecificStreamInfo = NULL;
/* Record some audio. -------------------------------------------- */
err = Pa_OpenStream(&stream, &inputParameters, NULL, hdr->sample_rate, paFramesPerBufferUnspecified, paClipOff, recordCallback, &data);
if(err) goto done;
if((err = Pa_StartStream(stream))) goto done;
puts("Now recording!! Please speak into the microphone.");
while((err = Pa_IsStreamActive(stream)) == 1)
{
Pa_Sleep(1000);
printf("index = %d\n", data.frameIndex);
}
if( err < 0 ) goto done;
err = Pa_CloseStream(stream);
if(err) goto done;
/* Measure maximum peak amplitude. */
max = 0;
average = 0.0;
for(int i = 0; i < numSamples; i++)
{
val = data.recordedSamples[i];
val = abs(val);
if( val > max )
{
max = val;
}
average += val;
}
average /= (double)numSamples;
{
FILE* fid = fopen(fileName, "wb");
if(!fid) printf("Could not open file.");
else
{
writeWAVHeader(fid, hdr);
fwrite(data.recordedSamples, hdr->number_of_channels, totalFrames, fid);
fclose(fid);
}
}
done:
Pa_Terminate();
if(data.recordedSamples) /* Sure it is NULL or valid. */
free(data.recordedSamples);
if(err)
{
fprintf(stderr, "An error occured while using the portaudio stream\n");
fprintf(stderr, "Error number: %d\n", err);
fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(err));
err = 1; /* Always return 0 or 1, but no other return codes. */
}
return err;
}
Some tests I ran on the file:
$ xxd -g1 test.wav | head
0000000: 52 49 46 46 00 00 00 30 00 00 00 30 57 41 56 45 RIFF...0...0WAVE
0000010: 66 6d 74 20 10 00 00 00 01 00 02 00 e0 ab 00 00 fmt ............
0000020: 80 af 02 00 04 00 10 00 57 41 56 45 66 6d 74 20 ........WAVEfmt
0000030: 66 6d 74 20 10 00 00 00 10 00 00 00 01 00 02 00 fmt ............
0000040: e0 ab 00 00 80 af 02 00 04 00 10 00 00 00 00 80 ................
0000050: 37 3d 04 10 00 00 03 00 01 00 02 00 e0 ab 00 00 7=..............
0000060: 80 af 02 00 04 00 10 00 02 00 e0 ab 00 00 80 af ................
0000070: 02 00 04 00 10 00 00 00 e0 ab 00 00 80 af 02 00 ................
0000080: 04 00 10 00 00 00 00 80 37 3d 04 10 00 00 03 00 ........7=......
0000090: 00 00 00 00 00 00 00 00 80 af 02 00 04 00 10 00 ................
$ file test.wav
test.wav: RIFF (little-endian) data
$ stat -f %s test.wav
stat: %s: bad format
I'm not quite sure where I am going wrong. Am I not writing out the data correctly?
I don't know about the rest of it, but your fwrites should be like this:
fwrite( hdr->RIFF_marker, sizeof(hdr->RIFF_marker), 1, fd);
fwrite(&hdr->file_size, sizeof(hdr->file_size), 1, fd);
fwrite( hdr->filetype_header, sizeof(hdr->filetype_header), 1, fd);
fwrite( hdr->format_marker, sizeof(hdr->format_marker), 1, fd);
fwrite(&hdr->data_header_length, sizeof(hdr->data_header_length), 1, fd);
fwrite(&hdr->format_type, sizeof(hdr->format_type), 1, fd);
fwrite(&hdr->number_of_channels, sizeof(hdr->number_of_channels), 1, fd);
fwrite(&hdr->sample_rate, sizeof(hdr->sample_rate), 1, fd);
fwrite(&hdr->bytes_per_second, sizeof(hdr->bytes_per_second), 1, fd);
fwrite(&hdr->bytes_per_frame, sizeof(hdr->bytes_per_frame), 1, fd);
fwrite(&hdr->bits_per_sample, sizeof(hdr->bits_per_sample), 1, fd);
fwrite("data", 4, 1, fd);