]> git.pld-linux.org Git - packages/dhcp_probe.git/blob - dhcp_probe-virta-01-pcap-loop.patch
- guignard-04_linux_32_or_64bits patch replaced by simple change to match Linux kerne...
[packages/dhcp_probe.git] / dhcp_probe-virta-01-pcap-loop.patch
1 ##dhcp-probe-01-pcap-loop.patch - wrap pcap_dispatch in a loop
2 --- src/dhcp_probe.c    2009-08-16 12:24:10.000000000 +0300
3 +++ src/dhcp_probe.c    2009-08-16 11:52:26.000000000 +0300
4 @@ -59,6 +59,7 @@
5  volatile sig_atomic_t reopen_log_file; /* for signal handler */
6  volatile sig_atomic_t reopen_capture_file; /* for signal handler */
7  volatile sig_atomic_t quit_requested; /* for signal requested */
8 +volatile sig_atomic_t alarm_fired; /* for signal requested */
9  
10  pcap_t *pd = NULL;                                     /* libpcap - packet capture descriptor used for actual packet capture */
11  pcap_t *pd_template = NULL;                    /* libpcap - packet capture descriptor just used as template */
12 @@ -74,6 +75,27 @@
13  int use_8021q = 0;
14  int vlan_id = 0;
15  
16 +/* capture packets from pcap for timeout seconds */
17 +int 
18 +loop_for_packets(int timeout)
19 +{
20 +       int packets_recv = 0;
21 +       
22 +       alarm_fired = 0;
23 +       alarm(timeout);
24 +       
25 +       do {
26 +               int pcap_rc = pcap_dispatch(pd, -1, process_response, NULL);
27 +               if (pcap_rc == -1)
28 +                       report(LOG_ERR, "pcap_dispatch(): %s", pcap_geterr(pd));
29 +               else if (pcap_rc > 0)
30 +                       packets_recv += pcap_rc;
31 +       } while(! alarm_fired && !quit_requested);
32 +       
33 +       return packets_recv;
34 +}
35 +
36 +
37  int 
38  main(int argc, char **argv)
39  {
40 @@ -84,7 +106,6 @@
41         struct sigaction sa;
42         FILE *pid_fp;
43         char *cwd = CWD;
44 -       int i;
45  
46         int write_packet_len;
47         int bytes_written;
48 @@ -98,9 +119,6 @@
49         int linktype;
50         char pcap_errbuf[PCAP_ERRBUF_SIZE], pcap_errbuf2[PCAP_ERRBUF_SIZE];
51  
52 -       /* for libnet */
53 -       char libnet_errbuf[LIBNET_ERRBUF_SIZE];
54 -
55         /* get progname = last component of argv[0] */
56         prog = strrchr(argv[0], '/');
57         if (prog)
58 @@ -265,6 +283,8 @@
59         reread_config_file = 0; /* set by signal handler */
60         reopen_log_file = 0; /* set by signal handler */
61         reopen_capture_file = 0; /* set by signal handler */
62 +       quit_requested = 0;
63 +       alarm_fired = 0;
64         
65         ifname = strdup(argv[optind]); /* interface name is a required final argument */
66  
67 @@ -332,6 +352,13 @@
68                 report(LOG_ERR, "sigaction: %s", get_errmsg());
69                 my_exit(1, 1, 1);
70         }
71 +       sigemptyset(&sa.sa_mask);
72 +       sa.sa_handler = catcher;
73 +       sa.sa_flags = 0;
74 +       if (sigaction(SIGALRM, &sa, NULL) < 0) {
75 +               report(LOG_ERR, "sigaction: %s", get_errmsg());
76 +               my_exit(1, 1, 1);
77 +       }
78  
79  
80  
81 @@ -479,8 +506,9 @@
82  
83                 for (l = libnet_cq_head(); libnet_cq_last(); l = libnet_cq_next()) { /* write one flavor packet and listen for answers */
84  
85 -                       int pcap_rc;
86 +                       int packets_recv;
87                         int pcap_open_retries;
88 +                       
89  
90                         /* We set up for packet capture BEFORE writing our packet, to minimize the delay
91                            between our writing and when we are able to start capturing.  (I cannot tell from
92 @@ -569,33 +597,16 @@
93                                 report(LOG_DEBUG, "listening for answers for %d milliseconds", GetResponse_wait_time());
94  
95  
96 -                       /* XXX I often find that pcap_dispatch() returns well before the timeout specified earlier.
97 -                          I ensure that there's no alarm() still left over before we start, and also ensure we don't
98 -                          get interrupted by SIGCHLD (possible since process_response() could fork an alert_program or alert_program2 child).
99 -                          But we STILL often return from pcap_dispatch() too soon!
100 -                          April 2001: An update to the pcap(3) man page around version 0.6 (?), along with postings 
101 -                          on the tcpdump workers mailing list explains what's going on.  The timeout specified in 
102 -                          pcap_open_live() isn't a timeout in the sense one might expect.  The pcap_dispatch() call 
103 -                          can return sooner than expected (even immediately), or if no packets are received, might 
104 -                          never return at all; the behavior is platform-dependant.  I don't have a way to work
105 -                          around this issue; it means this program  just won't work reliably (or at all) on some
106 -                          platforms.
107 -                       */
108 -
109 -                       alarm(0); /* just in case a previous alarm was still left */
110 -
111                         sigemptyset(&new_sigset);
112                         sigaddset(&new_sigset, SIGCHLD);
113                         sigprocmask(SIG_BLOCK, &new_sigset, &old_sigset);  /* block SIGCHLD */
114  
115 -                       pcap_rc = pcap_dispatch(pd, -1, process_response, NULL);
116 +                       packets_recv = loop_for_packets(GetResponse_wait_time() / 1000);;
117  
118                         sigprocmask(SIG_SETMASK, &old_sigset, NULL);  /* unblock SIGCHLD */
119  
120 -                       if (pcap_rc < 0)
121 -                               report(LOG_ERR, "pcap_dispatch(): %s", pcap_geterr(pd));
122 -                       else if (debug > 10)
123 -                               report(LOG_DEBUG, "done listening, captured %d packets", pcap_rc);
124 +                       if (debug > 10)
125 +                               report(LOG_DEBUG, "done listening, captured %d packets", packets_recv);
126  
127                         /* I was hoping that perhaps pcap_stats() would return a nonzero number of packets dropped when
128                            the buffer size specified to pcap_open_live() turns out to be too small -- so we could
129 @@ -688,6 +699,7 @@
130                 pcap_close(pd_template); 
131  
132         my_exit(0, 1, 1);
133 +       return 0; /* make gcc happy */
134  }
135  
136  
137 @@ -986,9 +998,6 @@
138  /* Perform all necessary functions to handle a request to reconfigure.
139     Must not be called until after initial configuration is complete.
140  */
141 -   
142 -       int i;
143 -
144         if (! read_configfile(config_file)) {
145                 my_exit(1, 1, 1);
146         }
147 @@ -1050,8 +1059,14 @@
148  
149         if ((sig == SIGINT) || (sig == SIGTERM) || (sig == SIGQUIT))  { /* quit gracefully */
150                 quit_requested = 1;
151 +                /* pcap wraps the socket read inside a loop, so the signal doesn't
152 +                   interrupt it without an explicit call to pcap_breakloop */
153 +               pcap_breakloop(pd);
154 +               return;
155 +       } else if (sig == SIGALRM) { /* timer */
156 +               pcap_breakloop(pd);
157 +               alarm_fired = 1;
158                 return;
159 -
160         } else if (sig == SIGHUP) { /* re-read config file */
161                 /* Doing the reread while in the signal handler is way too dangerous.
162                    We'll do it at the start or end of the next main event loop.
163
164
This page took 0.071645 seconds and 3 git commands to generate.