@@ -188,29 +188,30 @@ fn set_bindany(level: libc::c_int, socket: &Socket) -> io::Result<()> {
188
188
Ok ( ( ) )
189
189
}
190
190
191
- // #[cfg(target_os = "openbsd")]
192
- // fn set_bindany(_level: libc::c_int, socket: &Socket) -> io::Result<()> {
193
- // let fd = socket.as_raw_fd();
194
- //
195
- // let enable: libc::c_int = 1;
196
- //
197
- // // https://man.openbsd.org/getsockopt.2
198
- // unsafe {
199
- // let ret = libc::setsockopt(
200
- // fd,
201
- // libc::SOL_SOCKET,
202
- // libc::SO_BINDANY,
203
- // &enable as *const _ as *const _,
204
- // mem::size_of_val(&enable) as libc::socklen_t,
205
- // );
206
- // if ret != 0 {
207
- // return Err(Error::last_os_error());
208
- // }
209
- // }
210
- //
211
- // Ok(())
212
- // }
191
+ #[ cfg( target_os = "openbsd" ) ]
192
+ fn set_bindany ( _level : libc:: c_int , socket : & Socket ) -> io:: Result < ( ) > {
193
+ let fd = socket. as_raw_fd ( ) ;
194
+
195
+ let enable: libc:: c_int = 1 ;
196
+
197
+ // https://man.openbsd.org/getsockopt.2
198
+ unsafe {
199
+ let ret = libc:: setsockopt (
200
+ fd,
201
+ libc:: SOL_SOCKET ,
202
+ libc:: SO_BINDANY ,
203
+ & enable as * const _ as * const _ ,
204
+ mem:: size_of_val ( & enable) as libc:: socklen_t ,
205
+ ) ;
206
+ if ret != 0 {
207
+ return Err ( Error :: last_os_error ( ) ) ;
208
+ }
209
+ }
210
+
211
+ Ok ( ( ) )
212
+ }
213
213
214
+ #[ cfg( target_os = "freebsd" ) ]
214
215
fn set_ip_origdstaddr ( level : libc:: c_int , socket : & Socket ) -> io:: Result < ( ) > {
215
216
// https://www.freebsd.org/cgi/man.cgi?query=ip&sektion=4&manpath=FreeBSD+9.0-RELEASE
216
217
@@ -240,6 +241,52 @@ fn set_ip_origdstaddr(level: libc::c_int, socket: &Socket) -> io::Result<()> {
240
241
Ok ( ( ) )
241
242
}
242
243
244
+ #[ cfg( target_os = "openbsd" ) ]
245
+ fn set_ip_origdstaddr ( level : libc:: c_int , socket : & Socket ) -> io:: Result < ( ) > {
246
+ // https://man.openbsd.org/pf.conf
247
+ let fd = socket. as_raw_fd ( ) ;
248
+
249
+ let enable: libc:: c_int = 1 ;
250
+
251
+ let opt = match level {
252
+ libc:: IPPROTO_IP => libc:: IP_RECVDSTADDR ,
253
+ libc:: IPPROTO_IPV6 => libc:: IPV6_RECVPKTINFO ,
254
+ _ => unreachable ! ( "level can only be IPPROTO_IP or IPPROTO_IPV6" ) ,
255
+ } ;
256
+
257
+ unsafe {
258
+ let ret = libc:: setsockopt (
259
+ fd,
260
+ level,
261
+ opt,
262
+ & enable as * const _ as * const _ ,
263
+ mem:: size_of_val ( & enable) as libc:: socklen_t ,
264
+ ) ;
265
+ if ret != 0 {
266
+ return Err ( Error :: last_os_error ( ) ) ;
267
+ }
268
+ }
269
+
270
+ let opt2 = match level {
271
+ libc:: IPPROTO_IP => 33 , //libc::IP_RECVDSTPORT,
272
+ libc:: IPPROTO_IPV6 => 64 , //libc::IPV6_RECVDSTPORT,
273
+ _ => unreachable ! ( "level can only be IPPROTO_IP or IPPROTO_IPV6" ) ,
274
+ } ;
275
+ unsafe {
276
+ let ret = libc:: setsockopt (
277
+ fd,
278
+ level,
279
+ opt2,
280
+ & enable as * const _ as * const _ ,
281
+ mem:: size_of_val ( & enable) as libc:: socklen_t ,
282
+ ) ;
283
+ if ret != 0 {
284
+ return Err ( Error :: last_os_error ( ) ) ;
285
+ }
286
+ }
287
+ Ok ( ( ) )
288
+ }
289
+
243
290
fn set_disable_ip_fragmentation ( level : libc:: c_int , socket : & Socket ) -> io:: Result < ( ) > {
244
291
// https://www.freebsd.org/cgi/man.cgi?query=ip&sektion=4&manpath=FreeBSD+9.0-RELEASE
245
292
@@ -288,11 +335,13 @@ fn set_socket_before_bind(addr: &SocketAddr, socket: &Socket) -> io::Result<()>
288
335
set_ip_origdstaddr ( level, socket) ?;
289
336
290
337
// 3. disable IP fragmentation
338
+ #[ cfg( not( target_os = "openbsd" ) ) ] //seems unsupported in OpenBSD
291
339
set_disable_ip_fragmentation ( level, socket) ?;
292
340
293
341
Ok ( ( ) )
294
342
}
295
343
344
+ #[ cfg( target_os = "freebsd" ) ]
296
345
fn get_destination_addr ( msg : & libc:: msghdr ) -> io:: Result < SocketAddr > {
297
346
// https://www.freebsd.org/cgi/man.cgi?ip(4)
298
347
//
@@ -337,6 +386,50 @@ fn get_destination_addr(msg: &libc::msghdr) -> io::Result<SocketAddr> {
337
386
}
338
387
}
339
388
389
+ #[ cfg( target_os = "openbsd" ) ]
390
+ fn get_destination_addr ( msg : & libc:: msghdr ) -> io:: Result < SocketAddr > {
391
+ unsafe {
392
+ let ( _, addr) = SockAddr :: try_init ( |dst_addr, dst_addr_len| {
393
+ let mut cmsg: * mut libc:: cmsghdr = libc:: CMSG_FIRSTHDR ( msg) ;
394
+ let toaddr_in = & mut * ( dst_addr as * mut libc:: sockaddr_in ) ;
395
+ while !cmsg. is_null ( ) {
396
+ let rcmsg = & * cmsg;
397
+ match ( rcmsg. cmsg_level , rcmsg. cmsg_type ) {
398
+ ( libc:: IPPROTO_IP , libc:: IP_RECVDSTADDR ) => {
399
+ ptr:: copy_nonoverlapping (
400
+ libc:: CMSG_DATA ( cmsg) ,
401
+ & ( * toaddr_in) . sin_addr as * const _ as * mut _ ,
402
+ mem:: size_of :: < libc:: in_addr > ( ) ,
403
+ ) ;
404
+ toaddr_in. sin_family = libc:: AF_INET as u8 ;
405
+ * dst_addr_len = mem:: size_of :: < libc:: sockaddr_in > ( ) as libc:: socklen_t ;
406
+ }
407
+ ( libc:: IPPROTO_IP , 33 ) => { //libc::IP_RECVDSTPORT
408
+ ptr:: copy_nonoverlapping (
409
+ libc:: CMSG_DATA ( cmsg) ,
410
+ & ( * toaddr_in) . sin_port as * const _ as * mut _ ,
411
+ mem:: size_of :: < libc:: in_port_t > ( ) ,
412
+ ) ;
413
+ //assuming address comes first, and then port
414
+ return Ok ( ( ) ) ;
415
+ }
416
+ //TODO: support IPv6
417
+ // (libc::IPPROTO_IPV6, libc::IPV6_RECVPKTINFO) => {
418
+ // }
419
+ // (libc::IPPROTO_IPV6, libc::IPV6_RECVDSTPORT) => {
420
+ // }
421
+ _ => { }
422
+ }
423
+ cmsg = libc:: CMSG_NXTHDR ( msg, cmsg) ;
424
+ }
425
+ let err = Error :: new ( ErrorKind :: InvalidData , "missing destination address in msghdr" ) ;
426
+ Err ( err)
427
+ } ) ?;
428
+
429
+ Ok ( addr. as_socket ( ) . expect ( "SocketAddr" ) )
430
+ }
431
+ }
432
+
340
433
fn recv_dest_from ( socket : & UdpSocket , buf : & mut [ u8 ] ) -> io:: Result < ( usize , SocketAddr , SocketAddr ) > {
341
434
unsafe {
342
435
let mut control_buf = [ 0u8 ; 64 ] ;
0 commit comments