mysql.c 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. // https://dev.mysql.com/doc/dev/mysql-server/latest/PAGE_PROTOCOL.html
  2. #define MYSQL_COM_QUERY 3
  3. #define MYSQL_COM_STMT_PREPARE 0x16
  4. #define MYSQL_COM_STMT_EXECUTE 0x17
  5. #define MYSQL_COM_STMT_CLOSE 0x19
  6. #define MYSQL_RESPONSE_OK 0x00
  7. #define MYSQL_RESPONSE_EOF 0xfe
  8. #define MYSQL_RESPONSE_ERROR 0xff
  9. static __always_inline
  10. int is_mysql_query(char *buf, __u64 buf_size, __u8 *request_type) {
  11. if (buf_size < 5) {
  12. return 0;
  13. }
  14. __u8 b[5];
  15. bpf_read(buf, b);
  16. int length = (int)b[0] | (int)b[1] << 8 | (int)b[2] << 16;
  17. if (length+4 != buf_size || b[3] != 0) { // sequence must be 0
  18. return 0;
  19. }
  20. if (b[4] == MYSQL_COM_QUERY || b[4] == MYSQL_COM_STMT_EXECUTE) {
  21. return 1;
  22. }
  23. if (b[4] == MYSQL_COM_STMT_CLOSE) {
  24. *request_type = MYSQL_COM_STMT_CLOSE;
  25. return 1;
  26. }
  27. if (b[4] == MYSQL_COM_STMT_PREPARE) {
  28. *request_type = MYSQL_COM_STMT_PREPARE;
  29. return 1;
  30. }
  31. return 0;
  32. }
  33. static __always_inline
  34. int is_mysql_response(char *buf, __u64 buf_size, __u8 request_type, __u32 *statement_id, __u32 *status) {
  35. __u8 b[5];
  36. bpf_read(buf, b);
  37. if (b[3] < 1) { // sequence must be > 0
  38. return 0;
  39. }
  40. int length = (int)b[0] | (int)b[1] << 8 | (int)b[2] << 16;
  41. if (length == 1 || b[4] == MYSQL_RESPONSE_EOF) {
  42. *status = STATUS_OK;
  43. return 1;
  44. }
  45. if (b[4] == MYSQL_RESPONSE_OK ) {
  46. if (request_type == MYSQL_COM_STMT_PREPARE) {
  47. bpf_read(buf+5, *statement_id);
  48. }
  49. *status = STATUS_OK;
  50. return 1;
  51. }
  52. if (b[4] == MYSQL_RESPONSE_ERROR) {
  53. *status = STATUS_FAILED;
  54. return 1;
  55. }
  56. return 0;
  57. }