udp_test.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. #include <stdio.h>
  2. #include <stdint.h>
  3. #include <unistd.h>
  4. #include <string.h>
  5. #include <malloc.h>
  6. #define ETH_TYPE_ARP 0x0806
  7. #define ETH_TYPE_IP 0x0800
  8. #define PROTO_IP 0x800
  9. #define ARP_REQUEST 1
  10. #define ARP_REPLY 2
  11. #define PROTO_IP_UDP 0x11
  12. // size: 14
  13. typedef struct eth_header {
  14. uint8_t dest_mac[6];
  15. uint8_t src_mac[6];
  16. uint16_t type;
  17. uint8_t payload;
  18. } eth_header;
  19. // size: 28
  20. typedef struct arp_packet {
  21. uint16_t hwtype;
  22. uint16_t proto;
  23. uint8_t hwsize;
  24. uint8_t proto_size;
  25. uint16_t opcode;
  26. uint8_t sender_mac[6];
  27. uint8_t sender_ip[4];
  28. uint8_t target_mac[6];
  29. uint8_t target_ip[4];
  30. } arp_packet;
  31. // size: 20
  32. typedef struct ipv4_packet {
  33. uint8_t version;
  34. uint8_t services;
  35. uint16_t size;
  36. uint16_t id;
  37. uint8_t flags;
  38. uint8_t frag_offset; // 0x4000?
  39. uint8_t ttl;
  40. uint8_t proto;
  41. uint16_t checksum;
  42. uint8_t src_ip[4];
  43. uint8_t dest_ip[4];
  44. uint8_t data;
  45. } ipv4_packet;
  46. typedef struct udp_packet {
  47. uint16_t src_port;
  48. uint16_t dest_port;
  49. uint16_t size; // size-8 = body size in bytes
  50. uint16_t checksum;
  51. uint8_t data;
  52. } udp_packet;
  53. uint16_t swap16(uint16_t in) {
  54. uint16_t out = in<<8 | ((in&0xff00)>>8);
  55. return out;
  56. }
  57. char broadcast_mac[] = {0xff,0xff,0xff,0xff,0xff,0xff};
  58. char my_mac[] = {0x52,0x54,0xde,0xad,0xbe,0xef};
  59. char their_mac[] = {0xb6,0xc0,0x8e,0x06,0x82,0xdf,0x52,0x54};
  60. char my_ip[] = {10,0,0,4};
  61. char their_ip[] = {10,0,0,1};
  62. char* tx_packet;
  63. uint16_t cksum(uint16_t* ip, int len){
  64. long sum = 0; /* assume 32 bit long, 16 bit short */
  65. while(len > 1){
  66. uint16_t word = swap16(*ip);
  67. sum += word;
  68. ip++;
  69. if(sum & 0x80000000) { /* if high order bit set, fold */
  70. sum = (sum & 0xFFFF) + (sum >> 16);
  71. }
  72. len -= 2;
  73. }
  74. if(len) { /* take care of left over byte */
  75. sum += swap16((uint16_t) *(unsigned char *)ip);
  76. }
  77. while(sum>>16) {
  78. sum = (sum & 0xFFFF) + (sum >> 16);
  79. }
  80. return ~sum;
  81. }
  82. uint16_t udp_cksum(udp_packet* udp, ipv4_packet* i4, uint16_t len){
  83. long sum = 0; /* assume 32 bit long, 16 bit short */
  84. uint16_t* data = (uint16_t*)udp;
  85. uint16_t i = len;
  86. while(i > 1){
  87. uint16_t word = swap16(*data);
  88. sum += word;
  89. data++;
  90. if(sum & 0x80000000) /* if high order bit set, fold */
  91. sum = (sum & 0xFFFF) + (sum >> 16);
  92. i -= 2;
  93. }
  94. if (i) { /* take care of left over byte */
  95. uint16_t word = swap16((uint16_t) *(unsigned char *)data);
  96. sum += word;
  97. }
  98. // add pseudo header
  99. sum += swap16(((uint16_t*)i4->src_ip)[0]);
  100. sum += swap16(((uint16_t*)i4->src_ip)[1]);
  101. sum += swap16(((uint16_t*)i4->dest_ip)[0]);
  102. sum += swap16(((uint16_t*)i4->dest_ip)[1]);
  103. sum += 0x11;
  104. sum += len;
  105. while(sum>>16) {
  106. sum = (sum & 0xFFFF) + (sum >> 16);
  107. }
  108. return ~sum;
  109. }
  110. void machine_send_udp(char* sdata) {
  111. int len = strlen(sdata);
  112. uint8_t* data = (uint8_t*)sdata;
  113. eth_header* te = (eth_header*)tx_packet;
  114. memcpy(te->dest_mac, their_mac, 6);
  115. memcpy(te->src_mac, my_mac, 6);
  116. te->type = swap16(ETH_TYPE_IP);
  117. ipv4_packet* i4 = (ipv4_packet*)(((uint8_t*)te)+14);
  118. i4->version = (4<<4) | 5; // ipv4 + ihl5 (5*4 bytes header)
  119. i4->services = 0;
  120. i4->size = swap16(20+8+len); // patch later i4+udp
  121. i4->id = swap16(0x0000);
  122. i4->flags = 0x40; // don't fragment
  123. i4->frag_offset = 0; //
  124. i4->ttl = 0xff;
  125. i4->proto = PROTO_IP_UDP;
  126. i4->checksum = 0;
  127. memcpy(i4->src_ip, my_ip, 4);
  128. memcpy(i4->dest_ip, their_ip, 4);
  129. i4->checksum = swap16(cksum((uint16_t*)i4, 20));
  130. udp_packet* u = (udp_packet*)(&i4->data);
  131. u->dest_port = swap16(4001);
  132. u->src_port = swap16(4000);
  133. u->size = swap16(len+8);
  134. u->checksum = 0; // fixme
  135. memcpy(&u->data, data, len);
  136. int packet_len = len+8+20+14; // data + udp + i4 + eth
  137. u->checksum = udp_cksum(u, i4, len+8);
  138. printf("sending udp packet.\n");
  139. //b_ethernet_tx(tx_packet, packet_len);
  140. printf("checksum: %d %x\n",u->checksum,u->checksum);
  141. for (int i=0; i<4; i++) {
  142. uint8_t* b1 = ((uint8_t*)tx_packet)+i*16;
  143. uint8_t* b2 = ((uint8_t*)tx_packet)+i*16+8;
  144. printf("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
  145. b1[0],b1[1],b1[2],b1[3],b1[4],b1[5],b1[6],b1[7],
  146. b2[0],b2[1],b2[2],b2[3],b2[4],b2[5],b2[6],b2[7]);
  147. }
  148. }
  149. void main() {
  150. tx_packet = malloc(1024);
  151. machine_send_udp("hello world");
  152. }