pcap_user.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. /*
  2. * Copyright (C) 2002 Jeff Dike <jdike@karaya.com>
  3. * Licensed under the GPL.
  4. */
  5. #include <unistd.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <errno.h>
  9. #include <pcap.h>
  10. #include <asm/types.h>
  11. #include "net_user.h"
  12. #include "pcap_user.h"
  13. #include "user.h"
  14. #include "um_malloc.h"
  15. #define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER)
  16. #define PCAP_FD(p) (*(int *)(p))
  17. static int pcap_user_init(void *data, void *dev)
  18. {
  19. struct pcap_data *pri = data;
  20. pcap_t *p;
  21. char errors[PCAP_ERRBUF_SIZE];
  22. p = pcap_open_live(pri->host_if, MAX_PACKET, pri->promisc, 0, errors);
  23. if(p == NULL){
  24. printk("pcap_user_init : pcap_open_live failed - '%s'\n",
  25. errors);
  26. return -EINVAL;
  27. }
  28. pri->dev = dev;
  29. pri->pcap = p;
  30. return 0;
  31. }
  32. static int pcap_open(void *data)
  33. {
  34. struct pcap_data *pri = data;
  35. __u32 netmask;
  36. int err;
  37. if(pri->pcap == NULL)
  38. return -ENODEV;
  39. if(pri->filter != NULL){
  40. err = dev_netmask(pri->dev, &netmask);
  41. if(err < 0){
  42. printk("pcap_open : dev_netmask failed\n");
  43. return -EIO;
  44. }
  45. pri->compiled = um_kmalloc(sizeof(struct bpf_program));
  46. if(pri->compiled == NULL){
  47. printk("pcap_open : kmalloc failed\n");
  48. return -ENOMEM;
  49. }
  50. err = pcap_compile(pri->pcap,
  51. (struct bpf_program *) pri->compiled,
  52. pri->filter, pri->optimize, netmask);
  53. if(err < 0){
  54. printk("pcap_open : pcap_compile failed - '%s'\n",
  55. pcap_geterr(pri->pcap));
  56. return -EIO;
  57. }
  58. err = pcap_setfilter(pri->pcap, pri->compiled);
  59. if(err < 0){
  60. printk("pcap_open : pcap_setfilter failed - '%s'\n",
  61. pcap_geterr(pri->pcap));
  62. return -EIO;
  63. }
  64. }
  65. return PCAP_FD(pri->pcap);
  66. }
  67. static void pcap_remove(void *data)
  68. {
  69. struct pcap_data *pri = data;
  70. if(pri->compiled != NULL)
  71. pcap_freecode(pri->compiled);
  72. pcap_close(pri->pcap);
  73. }
  74. struct pcap_handler_data {
  75. char *buffer;
  76. int len;
  77. };
  78. static void handler(u_char *data, const struct pcap_pkthdr *header,
  79. const u_char *packet)
  80. {
  81. int len;
  82. struct pcap_handler_data *hdata = (struct pcap_handler_data *) data;
  83. len = hdata->len < header->caplen ? hdata->len : header->caplen;
  84. memcpy(hdata->buffer, packet, len);
  85. hdata->len = len;
  86. }
  87. int pcap_user_read(int fd, void *buffer, int len, struct pcap_data *pri)
  88. {
  89. struct pcap_handler_data hdata = ((struct pcap_handler_data)
  90. { .buffer = buffer,
  91. .len = len });
  92. int n;
  93. n = pcap_dispatch(pri->pcap, 1, handler, (u_char *) &hdata);
  94. if(n < 0){
  95. printk("pcap_dispatch failed - %s\n", pcap_geterr(pri->pcap));
  96. return -EIO;
  97. }
  98. else if(n == 0)
  99. return 0;
  100. return hdata.len;
  101. }
  102. const struct net_user_info pcap_user_info = {
  103. .init = pcap_user_init,
  104. .open = pcap_open,
  105. .close = NULL,
  106. .remove = pcap_remove,
  107. .set_mtu = NULL,
  108. .add_address = NULL,
  109. .delete_address = NULL,
  110. .max_packet = MAX_PACKET - ETH_HEADER_OTHER
  111. };