@@ -163,10 +163,27 @@ bpf_setfilter(int fd, value vfilter)
163163 return (r );
164164}
165165
166+ int
167+ bpf_setpromisc (int fd , int promisc )
168+ {
169+ int r = 0 ;
170+
171+ if (promisc ) {
172+ caml_enter_blocking_section ();
173+ r = ioctl (fd , BIOCPROMISC , NULL );
174+ caml_leave_blocking_section ();
175+ }
176+
177+ if (r == -1 )
178+ uerror ("bpf_setpromisc" , Nothing );
179+
180+ return (0 );
181+ }
182+
166183CAMLprim value
167- caml_rawlink_open (value vfilter , value vifname )
184+ caml_rawlink_open (value vfilter , value vpromisc , value vifname )
168185{
169- CAMLparam2 (vfilter , vifname );
186+ CAMLparam3 (vfilter , vpromisc , vifname );
170187 int fd ;
171188
172189 if ((fd = bpf_open ()) == -1 )
@@ -181,6 +198,8 @@ caml_rawlink_open(value vfilter, value vifname)
181198 CAMLreturn (Val_unit );
182199 if (bpf_setimmediate (fd , 1 ) == -1 )
183200 CAMLreturn (Val_unit );
201+ if (bpf_setpromisc (fd , Bool_val (vpromisc )) == -1 )
202+ CAMLreturn (Val_unit );
184203
185204 CAMLreturn (Val_int (fd ));
186205}
@@ -204,6 +223,34 @@ caml_bpf_align(value va, value vb)
204223
205224#ifdef USE_AF_PACKET
206225
226+ /*
227+ * Welcome to linux where glibc insists in not providing strlcpy.
228+ */
229+ size_t
230+ strlcpy (char * dst , const char * src , size_t dsize )
231+ {
232+ const char * osrc = src ;
233+ size_t nleft = dsize ;
234+
235+ /* Copy as many bytes as will fit. */
236+ if (nleft != 0 ) {
237+ while (-- nleft != 0 ) {
238+ if ((* dst ++ = * src ++ ) == '\0' )
239+ break ;
240+ }
241+ }
242+
243+ /* Not enough room in dst, add NUL and traverse rest of src. */
244+ if (nleft == 0 ) {
245+ if (dsize != 0 )
246+ * dst = '\0' ; /* NUL-terminate dst */
247+ while (* src ++ )
248+ ;
249+ }
250+
251+ return (src - osrc - 1 ); /* count does not include NUL */
252+ }
253+
207254#define FILTER sock_filter
208255
209256int
@@ -271,18 +318,48 @@ af_packet_setfilter(int fd, value vfilter)
271318 return (r );
272319}
273320
321+ int
322+ af_packet_setpromisc (int fd , int promisc , const char * ifname )
323+ {
324+ int r = 0 ;
325+ struct packet_mreq mr ;
326+ int ifidx ;
327+
328+ ifidx = if_nametoindex (ifname );
329+ if (ifidx == 0 )
330+ uerror ("af_set_promisc: if_nametoindex" , Nothing );
331+
332+ if (promisc ) {
333+ bzero (& mr , sizeof (mr ));
334+ mr .mr_ifindex = ifidx ;
335+ mr .mr_type = PACKET_MR_PROMISC ;
336+ caml_enter_blocking_section ();
337+ r = setsockopt (fd , SOL_PACKET , PACKET_ADD_MEMBERSHIP ,
338+ & mr , sizeof (mr ));
339+ caml_leave_blocking_section ();
340+ if (r == -1 )
341+ uerror ("af_set_promisc: PACKET_ADD_MEMBERSHIP" ,
342+ Nothing );
343+ }
344+
345+ return (r );
346+ }
347+
274348CAMLprim value
275- caml_rawlink_open (value vfilter , value vifname )
349+ caml_rawlink_open (value vfilter , value vpromisc , value vifname )
276350{
277- CAMLparam2 (vfilter , vifname );
351+ CAMLparam3 (vfilter , vpromisc , vifname );
278352 int fd ;
279353
280354 if ((fd = af_packet_open ()) == -1 )
281355 CAMLreturn (Val_unit );
282356 if (af_packet_setfilter (fd , vfilter ) == -1 )
283- CAMLreturn (Val_unit );
357+ CAMLreturn (Val_unit );
284358 if (af_packet_setif (fd , String_val (vifname )) == -1 )
285359 CAMLreturn (Val_unit );
360+ if (af_packet_setpromisc (fd , Bool_val (vpromisc ),
361+ String_val (vifname )) == -1 )
362+ CAMLreturn (Val_unit );
286363
287364 CAMLreturn (Val_int (fd ));
288365}
@@ -307,6 +384,7 @@ caml_driver(value vunit)
307384 CAMLreturn (Val_int (1 ));
308385#endif
309386}
387+
310388/* Filters */
311389CAMLprim value
312390caml_dhcp_server_filter (value vunit )
@@ -345,6 +423,7 @@ caml_dhcp_server_filter(value vunit)
345423
346424 CAMLreturn (vfilter );
347425}
426+
348427CAMLprim value
349428caml_dhcp_client_filter (value vunit )
350429{
0 commit comments